Passed
Push — master ( dd1fbc...6aef8a )
by Daimona
01:29
created

PageRiconferma::getCountForSection()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php declare( strict_types=1 );
2
3
namespace BotRiconferme\Page;
4
5
use BotRiconferme\Page\Page;
6
use BotRiconferme\WikiController;
7
8
/**
9
 * Represents a single riconferma page
10
 */
11
class PageRiconferma extends Page {
12
	// Sections of the page. The value is the section number
13
	const SECTION_SUPPORT = 3;
14
	const SECTION_OPPOSE = 4;
15
16
	// Possible outcomes of a vote
17
	const OUTCOME_OK = 0;
18
	const OUTCOME_FAIL_VOTES = 1;
19
	const OUTCOME_NO_QUOR = 2;
20
	const OUTCOME_FAIL = self::OUTCOME_FAIL_VOTES | self::OUTCOME_NO_QUOR;
21
22
	/**
23
	 * Get the name of the user from the title
24
	 *
25
	 * @return string
26
	 */
27
	public function getUser() : string {
28
		return explode( '/', $this->title )[2];
29
	}
30
31
	/**
32
	 * Returns the progressive number in the title
33
	 *
34
	 * @return int
35
	 */
36
	public function getNum() : int {
37
		$bits = explode( '/', $this->getTitle() );
38
		return intval( end( $bits ) );
39
	}
40
41
	/**
42
	 * Get the last part of the title as Username/Num
43
	 *
44
	 * @return string
45
	 */
46
	public function getUserNum() : string {
47
		return explode( '/', $this->getTitle(), 3 )[2];
48
	}
49
50
	/**
51
	 * Strip the part with the progressive number
52
	 *
53
	 * @return string
54
	 */
55
	public function getBaseTitle() : string {
56
		// @phan-suppress-next-line PhanTypeMismatchArgumentInternal Phan bug
57
		return substr( $this->getTitle(), 0, strrpos( $this->getTitle(), '/' ) );
58
	}
59
60
	/**
61
	 * Get the amount of opposing votes
62
	 *
63
	 * @return int
64
	 */
65
	public function getOpposingCount() : int {
66
		return $this->getCountForSection( self::SECTION_OPPOSE );
67
	}
68
69
	/**
70
	 * Get the amount support votes
71
	 *
72
	 * @return int
73
	 */
74
	public function getSupportCount() : int {
75
		return $this->getCountForSection( self::SECTION_SUPPORT );
76
	}
77
78
	/**
79
	 * Count the votes in the given section
80
	 *
81
	 * @param int $secNum
82
	 * @return int
83
	 */
84
	protected function getCountForSection( int $secNum ) : int {
85
		$content = $this->controller->getPageContent( $this->title, $secNum );
86
		// Let's hope that this is good enough...
87
		return substr_count( $content, "\n\# *(?![#*])" );
88
	}
89
90
	/**
91
	 * Gets the quorum used for the current page
92
	 *
93
	 * @return int
94
	 */
95
	protected function getQuorum() : int {
96
		$reg = "!soddisfare il \[\[[^|\]]+\|quorum]] di '''(\d+) voti'''!";
97
		$matches = [];
98
		preg_match( $reg, $this->getContent(), $matches );
99
		return intval( $matches[1] );
100
	}
101
102
	/**
103
	 * Whether this page has enough opposing votes
104
	 *
105
	 * @return bool
106
	 */
107
	public function hasOpposition() : bool {
108
		return $this->getOpposingCount() >= 15;
109
	}
110
111
	/**
112
	 * Gets the outcome for the vote
113
	 *
114
	 * @return int One of the OUTCOME_* constants
115
	 * @throws \BadMethodCallException
116
	 */
117
	public function getOutcome() : int {
118
		if ( !$this->isVote() ) {
119
			throw new \BadMethodCallException( 'Cannot get outcome for a non-vote page.' );
120
		}
121
		$totalVotes = $this->getOpposingCount() + $this->getSupportCount();
122
		if ( $this->getSupportCount() < $this->getQuorum() ) {
123
			return self::OUTCOME_NO_QUOR;
124
		} elseif ( $this->getSupportCount() < 2 * $totalVotes / 3 ) {
125
			return self::OUTCOME_FAIL_VOTES;
126
		}
127
		return self::OUTCOME_OK;
128
	}
129
130
	/**
131
	 * Get the result text for the page itself
132
	 *
133
	 * @return string
134
	 * @throws \BadMethodCallException
135
	 * @throws \LogicException
136
	 */
137
	public function getOutcomeText() : string {
138
		if ( !$this->isVote() ) {
139
			throw new \BadMethodCallException( 'No need for an outcome text.' );
140
		}
141
142
		$text = sprintf(
143
			' Con %d voti a favore e %d contrari',
144
			$this->getSupportCount(),
145
			$this->getOpposingCount()
146
		);
147
		$user = $this->getUser();
148
149
		switch ( $this->getOutcome() ) {
150
			case self::OUTCOME_OK:
151
				$text .= " $user viene riconfermato amministratore.";
152
				break;
153
			/** @noinspection PhpMissingBreakStatementInspection */
154
			case self::OUTCOME_NO_QUOR:
155
				$text .= ', non raggiungendo il quorum,';
156
				// Fall through intended
157
			case self::OUTCOME_FAIL:
158
				$text .= " $user non viene riconfermato amministratore";
159
				break;
160
			default:
161
				throw new \LogicException( 'Invalid outcome: ' . $this->getOutcome() );
162
		}
163
		return $text;
164
	}
165
166
	/**
167
	 * Whether this page is a vote
168
	 *
169
	 * @return bool
170
	 */
171
	public function isVote() : bool {
172
		$sectionReg = '/<!-- SEZIONE DA UTILIZZARE PER/';
173
		return preg_match( $sectionReg, $this->getContent() ) === false;
174
	}
175
176
	/**
177
	 * Get the end time
178
	 *
179
	 * @return int
180
	 */
181
	public function getEndTimestamp() : int {
182
		if ( $this->isVote() ) {
183
			$matches = [];
184
			$reg = "!La votazione ha inizio il.+ e ha termine.+ '''([^']+)''' alle ore '''([^']+)'''!";
185
			preg_match( $reg, $this->getContent(), $matches );
186
			list( , $day, $hours ) = $matches;
187
			$day = preg_replace( '![^\d \w]!', '', $day );
188
			return WikiController::getTimestampFromLocalTime( $day . " alle " . $hours );
189
		} else {
190
			$created = $this->controller->getPageCreationTS( $this->title );
191
			return $created + 60 * 60 * 24 * 7;
192
		}
193
	}
194
}
195