Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
77.78% covered (warning)
77.78%
21 / 27
55.56% covered (warning)
55.56%
5 / 9
CRAP
0.00% covered (danger)
0.00%
0 / 1
ChessSquare
77.78% covered (warning)
77.78%
21 / 27
55.56% covered (warning)
55.56%
5 / 9
12.33
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 newFromNumber
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
1
 newFromLateral64
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 newFromCoords
100.00% covered (success)
100.00%
12 / 12
100.00% covered (success)
100.00%
1 / 1
3
 getAsVertical64
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getCoords
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getNumber
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getRank
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getFile
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2/**
3 * This file is a part of ChessBrowser.
4 *
5 * ChessBrowser is free software: you can redistribute it and/or modify
6 *  it under the terms of the GNU General Public License as published by
7 *  the Free Software Foundation, either version 3 of the License, or
8 *  (at your option) any later version.
9 *
10 *  This program is distributed in the hope that it will be useful,
11 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 *  GNU General Public License for more details.
14 *
15 *  You should have received a copy of the GNU General Public License
16 *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
17 *
18 * @file ChessSquare
19 * @ingroup ChessBrowser
20 * @author DannyS712
21 */
22
23namespace MediaWiki\Extension\ChessBrowser;
24
25class ChessSquare {
26
27    /** @var string */
28    private $fileLetter;
29
30    /** @var int */
31    private $rankNumber;
32
33    /** @var int */
34    private $number;
35
36    public const NUMBER_TO_FILE = [
37        0 => 'a',
38        1 => 'b',
39        2 => 'c',
40        3 => 'd',
41        4 => 'e',
42        5 => 'f',
43        6 => 'g',
44        7 => 'h'
45    ];
46
47    public const FILE_TO_NUMBER = [
48        'a' => 0,
49        'b' => 1,
50        'c' => 2,
51        'd' => 3,
52        'e' => 4,
53        'f' => 5,
54        'g' => 6,
55        'h' => 7
56    ];
57
58    /**
59     * Doesn't apply validation, should not be called directly
60     *
61     * @param string $fileLetter
62     * @param int $rankNumber
63     * @param int $number
64     */
65    private function __construct( string $fileLetter, int $rankNumber, int $number ) {
66        $this->fileLetter = $fileLetter;
67        $this->rankNumber = $rankNumber;
68        $this->number = $number;
69    }
70
71    /**
72     * @param int $number
73     * @return ChessSquare
74     */
75    public static function newFromNumber( int $number ): ChessSquare {
76        return new ChessSquare(
77            self::NUMBER_TO_FILE[ $number & 0b00000111 ],
78            ( ( $number & 0b01110000 ) / 16 ) + 1,
79            $number
80        );
81    }
82
83    /**
84     * For conversion from a 0-63 representation which counted across rows
85     *
86     * @param int $number
87     * @return ChessSquare
88     */
89    public static function newFromLateral64( int $number ): ChessSquare {
90        $inHex = (int)( floor( $number / 8 ) * 16 ) + ( $number % 8 );
91        return self::newFromNumber( $inHex );
92    }
93
94    /**
95     * @param string $coords
96     * @return ChessSquare
97     * @throws ChessBrowserException if invalid
98     */
99    public static function newFromCoords( string $coords ): ChessSquare {
100        if ( strlen( $coords ) !== 2 ) {
101            throw new ChessBrowserException( "Coordinates ($coords) too long" );
102        }
103
104        [ $fileLetter, $rankNumber ] = str_split( $coords );
105        $rankNumber = intval( $rankNumber );
106
107        if ( !isset( self::FILE_TO_NUMBER[ $fileLetter ] ) ) {
108            throw new ChessBrowserException( "No such file: $fileLetter" );
109        }
110
111        $number = self::FILE_TO_NUMBER[ $fileLetter ] + ( 16 * ( $rankNumber - 1 ) );
112
113        return new ChessSquare(
114            $fileLetter,
115            $rankNumber,
116            $number
117        );
118    }
119
120    /**
121     * Get the 0-63 representation going up files
122     * A1=0; B1=1; etc
123     *
124     * @return int
125     */
126    public function getAsVertical64(): int {
127        return ( self::FILE_TO_NUMBER[$this->fileLetter] * 8 ) + ( $this->rankNumber - 1 );
128    }
129
130    /**
131     * Get the coordinates
132     *
133     * @return string
134     */
135    public function getCoords(): string {
136        return ( $this->fileLetter . $this->rankNumber );
137    }
138
139    /**
140     * Get the 0x88 location
141     *
142     * @return int
143     */
144    public function getNumber(): int {
145        return $this->number;
146    }
147
148    /**
149     * Get the rank number
150     *
151     * @return int
152     */
153    public function getRank(): int {
154        return $this->rankNumber;
155    }
156
157    /**
158     * Get the file letter
159     *
160     * @return string
161     */
162    public function getFile(): string {
163        return $this->fileLetter;
164    }
165
166}