Condorcet::addMethod()   A
last analyzed

Complexity

Conditions 4
Paths 3

Size

Total Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 4

Importance

Changes 0
Metric Value
cc 4
nc 3
nop 1
dl 0
loc 16
ccs 7
cts 7
cp 1
crap 4
rs 9.7333
c 0
b 0
f 0
1
<?php
2
/*
3
    Condorcet PHP - Election manager and results calculator.
4
    Designed for the Condorcet method. Integrating a large number of algorithms extending Condorcet. Expandable for all types of voting systems.
5
6
    By Julien Boudry and contributors - MIT LICENSE (Please read LICENSE.txt)
7
    https://github.com/julien-boudry/Condorcet
8
*/
9
declare(strict_types=1);
10
11
namespace CondorcetPHP\Condorcet;
12
13
use CondorcetPHP\Condorcet\Throwable\CondorcetException;
14
15
// Registering native Condorcet Methods implementation
16 9
Condorcet::addMethod( Algo\Methods\Borda\BordaCount::class );
17 9
Condorcet::addMethod( Algo\Methods\Copeland\Copeland::class );
18 9
Condorcet::addMethod( Algo\Methods\Dodgson\DodgsonQuick::class );
19 9
Condorcet::addMethod( Algo\Methods\Dodgson\DodgsonTidemanApproximation::class );
20 9
Condorcet::addMethod( Algo\Methods\Borda\DowdallSystem::class );
21 9
Condorcet::addMethod( Algo\Methods\Ftpt\Ftpt::class );
22 9
Condorcet::addMethod( Algo\Methods\InstantRunoff\InstantRunoff::class );
23 9
Condorcet::addMethod( Algo\Methods\KemenyYoung\KemenyYoung::class );
24 9
Condorcet::addMethod( Algo\Methods\Minimax\MinimaxWinning::class );
25 9
Condorcet::addMethod( Algo\Methods\Minimax\MinimaxMargin::class );
26 9
Condorcet::addMethod( Algo\Methods\Minimax\MinimaxOpposition::class );
27 9
Condorcet::addMethod( Algo\Methods\RankedPairs\RankedPairsMargin::class );
28 9
Condorcet::addMethod( Algo\Methods\RankedPairs\RankedPairsWinning::class );
29 9
Condorcet::addMethod( Algo\Methods\Schulze\SchulzeWinning::class );
30 9
Condorcet::addMethod( Algo\Methods\Schulze\SchulzeMargin::class );
31 9
Condorcet::addMethod( Algo\Methods\Schulze\SchulzeRatio::class );
32
33
// Set the default Condorcet Class algorithm
34 9
Condorcet::setDefaultMethod('Schulze');
35
36
abstract class Condorcet
37
{
38
39
/////////// CONSTANTS ///////////
40
    public const VERSION = '2.0.0';
41
42
    public const CONDORCET_BASIC_CLASS = Algo\Methods\CondorcetBasic::class;
43
44
    protected static $_defaultMethod = null;
45
    protected static $_authMethods = [ self::CONDORCET_BASIC_CLASS => (Algo\Methods\CondorcetBasic::class)::METHOD_NAME ];
46
47
48
/////////// STATICS METHODS ///////////
49
50
    // Return library version numer
51 7
    public static function getVersion (bool $major = false) : string
52
    {
53 7
        if ($major === true) :
54 4
            $version = explode('.', self::VERSION);
55 4
            return $version[0].'.'.$version[1];
56
        else :
57 5
            return self::VERSION;
58
        endif;
59
    }
60
61
    // Return an array with auth methods
62 1
    public static function getAuthMethods (bool $basic = false) : array
63
    {
64 1
        $auth = self::$_authMethods;
65
66
        // Don't show Natural Condorcet
67 1
        if (!$basic) :
68 1
            unset($auth[self::CONDORCET_BASIC_CLASS]);
69
        endif;
70
71 1
        return array_column($auth,0);
72
    }
73
74
75
    // Return the Class default method
76 16
    public static function getDefaultMethod () : ?string {
77 16
        return self::$_defaultMethod;
78
    }
79
80
81
    // Check if the method is supported
82 97
    public static function isAuthMethod (string $method)
83
    {
84 97
        $auth = self::$_authMethods;
85
86 97
        if (empty($method)) :
87 1
            throw new CondorcetException (8);
88
        endif;
89
90 96
        if ( isset($auth[$method]) ) :
91 12
            return $method;
92
        else : // Alias
93 94
            foreach ($auth as $class => $alias) :
94 94
                foreach ($alias as $entry) :
95 94
                    if ( strcasecmp($method,$entry) === 0 ) :
96 94
                        return $class;
97
                    endif;
98
                endforeach;
99
            endforeach;
100
        endif;
101
102 14
        return false;
103
    }
104
105
106
    // Add algos
107 13
    public static function addMethod (string $methodClass) : bool
108
    {
109
        // Check algos
110 13
        if ( self::isAuthMethod($methodClass) || !self::testMethod($methodClass) ) :
111 1
            return false;
112
        endif;
113
114
        // Adding algo
115 10
        self::$_authMethods[$methodClass] = $methodClass::METHOD_NAME;
116
117 10
        if (self::getDefaultMethod() === null) :
118 9
            self::setDefaultMethod($methodClass);
119
        endif;
120
121 10
        return true;
122
    }
123
124
125
        // Check if the class Algo. exist and ready to be used
126 12
        protected static function testMethod (string $method) : bool
127
        {
128 12
            if ( !class_exists($method) ) :             
129 1
                throw new CondorcetException(9);
130
            endif;
131
132 11
            if ( !is_subclass_of($method, Algo\MethodInterface::class) || !is_subclass_of($method, Algo\Method::class) ) :
0 ignored issues
show
Bug introduced by
Due to PHP Bug #53727, is_subclass_of might return inconsistent results on some PHP versions if \CondorcetPHP\Condorcet\...\MethodInterface::class can be an interface. If so, you could instead use ReflectionClass::implementsInterface.
Loading history...
Bug introduced by
Due to PHP Bug #53727, is_subclass_of might return inconsistent results on some PHP versions if \CondorcetPHP\Condorcet\Algo\Method::class can be an interface. If so, you could instead use ReflectionClass::implementsInterface.
Loading history...
133 1
                throw new CondorcetException(10);
134
            endif;
135
136 10
            foreach ($method::METHOD_NAME as $alias) :
137 10
                if (self::isAuthMethod($alias)) :
138 10
                    throw new CondorcetException(25);
139
                endif;
140
            endforeach;
141
142 10
            return true;
143
        }
144
145
146
    // Change default method for this class.
147 10
    public static function setDefaultMethod (string $method) : bool
148
    {       
149 10
        if ( ($method = self::isAuthMethod($method)) && $method !== self::CONDORCET_BASIC_CLASS ) :
150 9
            self::$_defaultMethod = $method;
151 9
            return true;
152
        else :
153 1
            return false;
154
        endif;
155
    }
156
157 94
    public static function condorcetBasicSubstitution (?string $substitution) : string
158
    {
159 94
        if ( $substitution !== null ) :
160 51
            if ( Condorcet::isAuthMethod($substitution) ) :
161 51
                $algo = $substitution;
162
            else :
163 51
                throw new CondorcetException(9,$substitution);
164
            endif;
165
        else :
166 92
            $algo = Condorcet::CONDORCET_BASIC_CLASS;
167
        endif;
168
169 94
        return $algo;
170
    }
171
}
172