Skip to content

Commit 71fdc48

Browse files
committed
Add team splitter technical interview task
1 parent 6d14d6c commit 71fdc48

11 files changed

+205
-28
lines changed

composer.json

+6-6
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,20 @@
33
"description": "Code Katas with PHPUnit",
44
"type": "package",
55
"require": {
6-
"php": "^7.3",
6+
"php": "^8.1",
77
"ext-json": "*",
8-
"symfony/var-dumper": "^5.0",
9-
"phpunit/phpunit": "^8.4|^9.0",
10-
"ext-dom": "20031129"
8+
"symfony/var-dumper": "^6.0",
9+
"phpunit/phpunit": "^9.5",
10+
"ext-dom": "*"
1111
},
1212
"autoload": {
1313
"psr-4": {
14-
"Katas\\": "src/Katas/"
14+
"Katas\\": "src/Katas"
1515
}
1616
},
1717
"autoload-dev": {
1818
"psr-4": {
19-
"Katas\\Tests\\": "tests/"
19+
"Katas\\Tests\\": "tests"
2020
}
2121
}
2222
}

resources/data/players.json

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
[
2+
{
3+
"name": "Chris R",
4+
"score": 0.58
5+
},
6+
{
7+
"name": "Joe B",
8+
"score": 0.57
9+
},
10+
{
11+
"name": "Martin T",
12+
"score": 0.57
13+
},
14+
{
15+
"name": "Jasmine A",
16+
"score": 0.55
17+
},
18+
{
19+
"name": "Luke F",
20+
"score": 0.54
21+
},
22+
{
23+
"name": "Tom L",
24+
"score": 0.53
25+
},
26+
{
27+
"name": "Dale J",
28+
"score": 0.53
29+
},
30+
{
31+
"name": "Lucy H",
32+
"score": 0.53
33+
},
34+
{
35+
"name": "Robert B",
36+
"score": 0.53
37+
},
38+
{
39+
"name": "Terry V",
40+
"score": 0.48
41+
}
42+
]

src/Katas/BowlingGame.php

+18-11
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ class BowlingGame extends Kata implements Executable
99
/**
1010
* The number of frames in a game.
1111
*/
12-
const FRAMES_PER_GAME = 10;
12+
public const FRAMES_PER_GAME = 10;
1313

1414
/**
1515
* All rolls for the game.
@@ -31,7 +31,8 @@ public function execute(...$arguments)
3131
/**
3232
* Roll the ball.
3333
*
34-
* @param int $pins
34+
* @param int $pins
35+
*
3536
* @return void
3637
*/
3738
public function roll(int $pins): void
@@ -53,7 +54,7 @@ public function score()
5354
if ($this->isStrike($roll)) {
5455
$score += $this->pinCount($roll) + $this->strikeBonus($roll);
5556

56-
$roll += 1;
57+
++$roll;
5758

5859
continue;
5960
}
@@ -73,29 +74,32 @@ public function score()
7374
/**
7475
* Determine if the current roll was a strike.
7576
*
76-
* @param int $roll
77+
* @param int $roll
78+
*
7779
* @return bool
7880
*/
7981
protected function isStrike(int $roll): bool
8082
{
81-
return $this->pinCount($roll) === 10;
83+
return 10 === $this->pinCount($roll);
8284
}
8385

8486
/**
8587
* Determine if the current frame was a spare.
8688
*
87-
* @param int $roll
89+
* @param int $roll
90+
*
8891
* @return bool
8992
*/
9093
protected function isSpare(int $roll): bool
9194
{
92-
return $this->defaultFrameScore($roll) === 10;
95+
return 10 === $this->defaultFrameScore($roll);
9396
}
9497

9598
/**
9699
* Calculate the score for the frame.
97100
*
98-
* @param int $roll
101+
* @param int $roll
102+
*
99103
* @return int
100104
*/
101105
protected function defaultFrameScore(int $roll): int
@@ -106,7 +110,8 @@ protected function defaultFrameScore(int $roll): int
106110
/**
107111
* Get the bonus for a strike.
108112
*
109-
* @param int $roll
113+
* @param int $roll
114+
*
110115
* @return int
111116
*/
112117
protected function strikeBonus(int $roll): int
@@ -117,7 +122,8 @@ protected function strikeBonus(int $roll): int
117122
/**
118123
* Get the bonus for a spare.
119124
*
120-
* @param int $roll
125+
* @param int $roll
126+
*
121127
* @return int
122128
*/
123129
protected function spareBonus(int $roll): int
@@ -128,7 +134,8 @@ protected function spareBonus(int $roll): int
128134
/**
129135
* Get the number of pins knocked down for the given roll.
130136
*
131-
* @param int $roll
137+
* @param int $roll
138+
*
132139
* @return int
133140
*/
134141
protected function pinCount(int $roll): int

src/Katas/Contracts/Executable.php

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ interface Executable
88
* Make class compatible to a single executable method.
99
*
1010
* @param mixed $arguments
11+
*
1112
* @return void
1213
*/
1314
public function execute(...$arguments);

src/Katas/FizzBuzz.php

+4-3
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,19 @@ public function execute(...$arguments)
1717
/**
1818
* Give appropriate term of number being checked.
1919
*
20-
* @param int $number
20+
* @param int $number
21+
*
2122
* @return string
2223
*/
2324
public function convert(int $number): string
2425
{
2526
$result = '';
2627

27-
if ($number % 3 === 0) {
28+
if (0 === $number % 3) {
2829
$result .= 'Fizz';
2930
}
3031

31-
if ($number % 5 === 0) {
32+
if (0 === $number % 5) {
3233
$result .= 'Buzz';
3334
}
3435

src/Katas/PrimeFactors.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ public function execute(...$arguments)
3131
/**
3232
* Generate prime factors of given numbers.
3333
*
34-
* @param integer $number
34+
* @param int $number
35+
*
3536
* @return array
3637
*/
3738
public function generate(int $number): array

src/Katas/RomanNumerals.php

+3-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ class RomanNumerals extends Kata implements Executable
99
/**
1010
* Numeral symbol lookup.
1111
*/
12-
const NUMERALS = [
12+
public const NUMERALS = [
1313
'M' => 1000,
1414
'CM' => 900,
1515
'D' => 500,
@@ -36,7 +36,8 @@ public function execute(...$arguments)
3636
/**
3737
* Generate respective roman numeral representation of given number.
3838
*
39-
* @param integer $number
39+
* @param int $number
40+
*
4041
* @return string
4142
*/
4243
public function generate(int $number)

src/Katas/StringCalculator.php

+9-5
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ class StringCalculator extends Kata implements Executable
1010
/**
1111
* The mamximum number allowed to be calculated.
1212
*/
13-
const MAX_NUMBER_ALLOWED = 1000;
13+
public const MAX_NUMBER_ALLOWED = 1000;
1414

1515
/**
1616
* Acceptable delimeters.
@@ -31,6 +31,7 @@ public function execute(...$arguments)
3131
* Sum up the given string as integers.
3232
*
3333
* @param string $numbers
34+
*
3435
* @return int
3536
*
3637
* @throws \InvalidArgumentException
@@ -48,7 +49,8 @@ public function add(string $numbers): int
4849
/**
4950
* Identify and parse given parameter.
5051
*
51-
* @param string $numbers
52+
* @param string $numbers
53+
*
5254
* @return array
5355
*/
5456
protected function parseString(string $numbers): array
@@ -73,7 +75,8 @@ protected function parseString(string $numbers): array
7375
/**
7476
* Determine if geven array of numbers are positive integers.
7577
*
76-
* @param array $numbers
78+
* @param array $numbers
79+
*
7780
* @return \Katas\StringCalculator
7881
*/
7982
protected function disallowNegativeNumbers(array $numbers): StringCalculator
@@ -90,9 +93,10 @@ protected function disallowNegativeNumbers(array $numbers): StringCalculator
9093
}
9194

9295
/**
93-
* Determine if each integer in the given array is below 1000
96+
* Determine if each integer in the given array is below 1000.
97+
*
98+
* @param array $numbers
9499
*
95-
* @param array $numbers
96100
* @return array
97101
*/
98102
protected function ignoreGreateThanOneThousand(array $numbers): array

src/Katas/Support/Arr.php

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
namespace Katas\Support;
4+
5+
class Arr
6+
{
7+
/**
8+
* Pluck an array of values from an array. (Only for PHP 5.3+).
9+
*
10+
* @param $array - data
11+
* @param $key - value you want to pluck from array
12+
*
13+
* @return array - plucked array only with key data
14+
*/
15+
public static function pluck($array, $key)
16+
{
17+
return array_map(function ($v) use ($key) {
18+
return is_object($v) ? $v->$key : $v[$key];
19+
}, $array);
20+
}
21+
}

src/Katas/TeamMaker.php

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<?php
2+
3+
namespace Katas;
4+
5+
use Katas\Support\Arr;
6+
use Katas\Contracts\Executable;
7+
8+
/**
9+
* Story.
10+
*
11+
* As the owner of a local 5-a-side football team, I want to generate as evenly balanced
12+
* teams as possible so that matches are fair and competitive. You should also have
13+
* received a JSON list of player names and rankings.
14+
*
15+
* Acceptance Criteria.
16+
*
17+
* Each team should consist of 5 players and be as evenly ranked as possible.
18+
*/
19+
class TeamMaker extends Kata implements Executable
20+
{
21+
/**
22+
* {@inheritDoc}
23+
*/
24+
public function execute(...$arguments)
25+
{
26+
do {
27+
[$team1, $team2] = $this->makeTeam($arguments[0]);
28+
29+
$teamScore1 = round($this->getTeamRanking($team1));
30+
$teamScore2 = round($this->getTeamRanking($team2));
31+
} while ($teamScore1 !== $teamScore2);
32+
33+
return [$team1, $team2];
34+
}
35+
36+
/**
37+
* Generate two teams.
38+
*
39+
* @param array $players
40+
* @param int $size
41+
*
42+
* @return array
43+
*/
44+
public function makeTeam($players, $size = 5)
45+
{
46+
shuffle($players);
47+
48+
return array_chunk($players, $size);
49+
}
50+
51+
/**
52+
* Extract the scores of each player and sum it up
53+
* resulting in the total score for the team.
54+
*
55+
* @param array $team
56+
*
57+
* @return float
58+
*/
59+
public function getTeamRanking($team)
60+
{
61+
return array_sum(Arr::pluck($team, 'score'));
62+
}
63+
}

tests/TeamMakerTest.php

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php
2+
3+
namespace Katas\Tests;
4+
5+
use Katas\TeamMaker;
6+
use PHPUnit\Framework\TestCase;
7+
8+
/**
9+
* Story.
10+
*
11+
* As the owner of a local 5-a-side football team, I want to generate as evenly balanced
12+
* teams as possible so that matches are fair and competitive. You should also have
13+
* received a JSON list of player names and rankings.
14+
*
15+
* Acceptance Criteria.
16+
*
17+
* Each team should consist of 5 players and be as evenly ranked as possible.
18+
*/
19+
class TeamMakerTest extends TestCase
20+
{
21+
public function testTwoTeamsWithEqualScoringAreGenerated()
22+
{
23+
$maker = new TeamMaker();
24+
$players = json_decode(
25+
\file_get_contents(__DIR__ . '/../resources/data/players.json'),
26+
true
27+
);
28+
29+
[$team1, $team2] = $maker->execute($players);
30+
31+
$this->assertEquals(
32+
round($maker->getTeamRanking($team1)),
33+
round($maker->getTeamRanking($team2))
34+
);
35+
}
36+
}

0 commit comments

Comments
 (0)