Page MenuHomePhabricator

Make STVTallier::getTextResult() output wikitext
Open, HighPublic

Description

At the time of writing (20th August, 2021), STVTallier::getTextResult() returns the HTML string generated by ::getHtmlResult(). This satisfies the immediate need that the user can copy+paste the result elsewhere but has a couple of issues:

  1. The output is unreadable
  2. The output relies on CSS that might not available on other wikis (including on the Wikipedias)

Making ::getTextResult() return wikitext address these issues.

Notes

  • We might be able to flip the relationship between ::getTextResult() and ::getHtmlResult() – the latter could use the wikitext parser on the output of the former
  • If we don't do the above, then both methods will share a lot of the same code – iteration over rounds and sorting of various sets of data. We should extract an interface for formatting the results of this particular tallier, e.g.
includes/Talliers/Stv/StvFormatter.php
namespace MediaWiki\Extensions\SecurePoll\Talliers\Stv;

interface StvFormatter {
    function formatPreamble( array $elected, array $eliminated ): string;

    function formatRoundsPreamble(): string;

    function formatRound( array $round ): string
}

The wikitext and HTML formatters would be implemented in MediaWiki\Extensions\SecurePoll\Talliers\Stv\WikitextFormatter and HtmlFormatter, respectively. Both classes would have one responsibility and no collaborators so they would be relatively easy to test.

Event Timeline

jrbs triaged this task as High priority.Sep 23 2022, 10:28 PM
jrbs moved this task from Backlog to Needs evaluation on the MediaWiki-extensions-SecurePoll board.

Change 855568 had a related patch set uploaded (by Pavlo Yashchenko; author: Pavlo Yashchenko):

[mediawiki/extensions/SecurePoll@master] Wikitext formatter in STVtallier

https://gerrit.wikimedia.org/r/855568

Evaluation:

Simple change, low risk. few days

Change 1006920 had a related patch set uploaded (by Mschlindwein; author: Mschlindwein):

[mediawiki/extensions/SecurePoll@master] Add formatter for STVTallier

https://gerrit.wikimedia.org/r/1006920

Change 855568 abandoned by Foks:

[mediawiki/extensions/SecurePoll@master] Wikitext formatter in STVtallier

Reason:

Abandoning on request. New commit was filed instead

https://gerrit.wikimedia.org/r/855568

Hi @TAdeleye_WMF @Miriamin,

I pulled this down for a more thorough code review today, and realized that I'm not clear what the actual acceptance criteria is here. From the description, I would expect garbled tally output for STV poll tallies, but the output from master seems fine?

image.png (345×474 px, 10 KB)

I double checked in the cli:

$ docker compose exec mediawiki bash -c "php extensions/SecurePoll/cli/tally.php --name 'stv 2'"

*******************************************************************************
NOTE: Do not run maintenance scripts directly, use maintenance/run.php instead!
      Running scripts directly has been deprecated in MediaWiki 1.40.
      It may not work for some (or any) scripts in the future.
*******************************************************************************

1
1          | 1
2          | 0
3          | 0

Script finished in 0 s

The output seems identical between the patch and master. I'm not really sure what user facing problem I'm trying to reproduce in order to validate the solution.

I'm definitely no expert in SecurePoll workflows, so I may be missing something obvious. Please let me know!

@jsn.sherman from what I was told, it should allow getting html and wikitext result, because the current state is that getTextResult returns also an html string but should be wikitext. If I run the tally.php it will be wikitext and if I add --html i will get html string and this should be everything for this task. That's what I know about it

@jsn.sherman from what I was told, it should allow getting html and wikitext result, because the current state is that getTextResult returns also an html string but should be wikitext. If I run the tally.php it will be wikitext and if I add --html i will get html string and this should be everything for this task. That's what I know about it

I dug in the source a little bit to try to find out when the stv tallier would be called:
https://gerrit.wikimedia.org/r/plugins/gitiles/mediawiki/extensions/SecurePoll/+/refs/heads/master/includes/Talliers/Tallier.php#74

	public static $tallierTypes = [
		'plurality' => PluralityTallier::class,
		'schulze' => SchulzeTallier::class,
		'histogram-range' => HistogramRangeTallier::class,
		'droop-quota' => STVTallier::class,
	];

It looks like this tallier gets called when "droop quota" is set in the poll. When I set that and then tally the poll, I can see a big difference between the text output and the html output.
text tally from master:

<div class='election-tally-results--stv oo-ui-layout oo-ui-panelLayout oo-ui-panelLayout-scrollable oo-ui-stackLayout oo-ui-stackLayout-continuous'><div class='oo-ui-layout oo-ui-panelLayout'><h2>Elected</h2><p>Election for 10 seats with 3 candidates. Total 2 votes.</p><ol class='election-summary-elected-list'><li>1</li><li>3</li><li>2</li><li><i>This seat could not be filled because no candidates fulfill the criteria. The last eliminated candidates were: </i></li><li><i>This seat could not be filled because no candidates fulfill the criteria. The last eliminated candidates were: </i></li><li><i>This seat could not be filled because no candidates fulfill the criteria. The last eliminated candidates were: </i></li><li><i>This seat could not be filled because no candidates fulfill the criteria. The last eliminated candidates were: </i></li><li><i>This seat could not be filled because no candidates fulfill the criteria. The last eliminated candidates were: </i></li><li><i>This seat could not be filled because no candidates fulfill the criteria. The last eliminated candidates were: </i></li><li><i>This seat could not be filled because no candidates fulfill the criteria. The last eliminated candidates were: </i></li></ol><h2>Eliminated/Not elected</h2><ul></ul></div><div class='oo-ui-layout oo-ui-panelLayout'><h2>Rounds table</h2><p>The following table describes the calculations that happened in order to achieve the result above. In each round of calculation, the candidate(s) who achieved more votes than the quota are declared elected. Their surplus votes above the quota are redistributed to the remaining candidates. If nobody achieves the quota, the lowest ranking candidate is eliminated and their votes are redistributed to the remaining candidates. To understand this better, please refer to <a rel="nofollow" class="external text" href="https://web.archive.org/web/20210225045400/https://prfound.org/resources/reference/reference-meek-rule/">this link</a>.</p><table class='wikitable'><thead><tr><th>Round Number</th><th>Tally</th><th>Result</th></tr></thead><tbody><tr><td>1</td><td><ol class='round-summary-tally-list'><li><span class='round-summary-candidate-name'>1: </span><span class='round-summary-candidate-votes'>1</span></li><li><span class='round-summary-candidate-name'>3: </span><span class='round-summary-candidate-votes'>1</span></li><li><span class='round-summary-candidate-name'>2: </span><span class='round-summary-candidate-votes'>0</span></li></ol></td><td>Quota: 0.181819<br /></td></tr><tr><td>2</td><td><ol class='round-summary-tally-list'><li class='round-candidate-elected'><span class='round-summary-candidate-name'>1: </span><span class='round-summary-candidate-votes'>1</span></li><li class='round-candidate-elected'><span class='round-summary-candidate-name'>3: </span><span class='round-summary-candidate-votes'>1</span></li><li><span class='round-summary-candidate-name'>2: </span><span class='round-summary-candidate-votes'>0</span></li></ol></td><td>Quota: 0.181819<br />Elected: 1, 3<br /></td></tr><tr><td>3</td><td><ol class='round-summary-tally-list'><li class='round-candidate-elected'><span class='round-summary-candidate-name'>2: </span><span class='round-summary-candidate-votes'>0 + 1.636362 = 1.636362</span></li><li class='previously-elected'><span class='round-summary-candidate-name'>1: </span><span class='round-summary-candidate-votes'>1 - 0.818181 = 0.181819 (keep factor: 0.181819)</span></li><li class='previously-elected'><span class='round-summary-candidate-name'>3: </span><span class='round-summary-candidate-votes'>1 - 0.818181 = 0.181819 (keep factor: 0.181819)</span></li></ol></td><td>Quota: 0.181819<br />Elected: 2<br />Transferring votes<br /></td></tr></tbody></table></div></div>

text tally from your patch

==Elected==
Election for 10 seats with 3 candidates. Total 2 votes.
* 1
* 3
* 2
* ''This seat could not be filled because no candidates fulfill the criteria. The last eliminated candidates were: ''
* ''This seat could not be filled because no candidates fulfill the criteria. The last eliminated candidates were: ''
* ''This seat could not be filled because no candidates fulfill the criteria. The last eliminated candidates were: ''
* ''This seat could not be filled because no candidates fulfill the criteria. The last eliminated candidates were: ''
* ''This seat could not be filled because no candidates fulfill the criteria. The last eliminated candidates were: ''
* ''This seat could not be filled because no candidates fulfill the criteria. The last eliminated candidates were: ''
* ''This seat could not be filled because no candidates fulfill the criteria. The last eliminated candidates were: ''
==Eliminated/Not elected==
==Rounds table==
{| class="wikitable"
!Round Number
!Tally
!Result
|-
|1
|
*1: 1
*3: 1
*2: 0
|Quota: 0.181819

|-
|2
|
*1: 1
*3: 1
*2: 0
|Quota: 0.181819
Elected: 1, 3

|-
|3
|
*2: 0 + 1.636362 = 1.636362
*1: 1 - 0.818181 = 0.181819 (keep factor: 0.181819)
*3: 1 - 0.818181 = 0.181819 (keep factor: 0.181819)
|Quota: 0.181819
Elected: 2

Transferring votes

Change #1006920 merged by jenkins-bot:

[mediawiki/extensions/SecurePoll@master] Add formatter for STVTallier

https://gerrit.wikimedia.org/r/1006920

This is ready for QA ahead of the next train.

Change #1030228 had a related patch set uploaded (by Jsn.sherman; author: Jsn.sherman):

[mediawiki/extensions/SecurePoll@master] WIP STVFormatter: don't use global wfMessage()

https://gerrit.wikimedia.org/r/1030228