AJ Madison’s code test/skills assessment was in TestDome. It was stated to be 1h without pre-requisites. It’s 02:50 average, 04:15 max, due in 5d, and has pre-requisites (which later per instruction’s cloud equivalents were unnecessary locally):

  1. get PHP 7.3.10, 7.3.24 is included in macOS:
    php -a
    

    or in Docker

    docker run -it --rm php:7.3.10-cli bash
    
  2. get MySQL 8.0 (its dockerhub has wrong cmds!):
    #start server
    docker run --name ajmmysql -e MYSQL_ROOT_PASSWORD=pw -d mysql:8.0
    #start client
    docker exec -it ajmmysql mysql -uroot -p
    
  3. get SQLite 3.28, 3.32.3 is included in macOS:
    sqlite3
    

    or in Docker is 3.34.0:

    docker run --rm -it keinos/sqlite3
    

Now the test itself. 1. question

class CropRatio
{
    private $totalWeight;
    private $crops = [];

    public function add(string $name, int $cropWeight) : void
    {
        $currentCropWeight = 0;
        if(!array_key_exists($name, $this->crops)) {
            $this->crops[$name] = $currentCropWeight;
        }

        $currentCropWeight += $cropWeight;
        $this->totalWeight++;
    }

    public function proportion(string $name) : float
    {
        return $this->crops[$name] / $this->totalWeight;
    }
}

$cropRatio = new CropRatio;
$cropRatio->add('Wheat', 4);
$cropRatio->add('Wheat', 5);
$cropRatio->add('Rice', 1);

echo "Wheat: " . $cropRatio->proportion('Wheat');

answer passed 3/3 cases

class CropRatio
{
    private $totalWeight = 0;
    private $crops = [];

    public function add(string $name, int $cropWeight) : void
    {
        if(array_key_exists($name, $this->crops)) {
            $this->crops[$name] += $cropWeight;
            $this->totalWeight += $cropWeight;
        } else {
            $this->crops[$name] = 0;
        }
    }

    public function proportion(string $name) : float
    {
        return $this->crops[$name] / $this->totalWeight;
    }
}

$cropRatio = new CropRatio;
$cropRatio->add('Wheat', 4);
$cropRatio->add('Wheat', 5);
$cropRatio->add('Rice', 1);

2. question

class CategoryTree
{
    public function addCategory(string $category, string $parent=null) : void
    {

    }

    public function getChildren(string $parent) : array
    {
        return [];
    }
}

$c = new CategoryTree;
$c->addCategory('A', null);
$c->addCategory('B', 'A');
$c->addCategory('C', 'A');
echo implode(',', $c->getChildren('A'));

answer passed 4/4 cases

class CategoryTree
{
    private $roots = [];

    public function addCategory(string $category, string $parent=null) : void
    {
        if(array_key_exists($category, $this->roots)) {
            throw new InvalidArgumentException();
        }
        else {
            if($parent && !array_key_exists($parent, $this->roots)) {
                throw new InvalidArgumentException();
            }
            else {
                $this->roots[$category] = $parent;
            }
        }
    }

    public function getChildren(string $parent) : array
    {
        if(!in_array($parent, $this->roots)) {
           throw new InvalidArgumentException();
        }
        else {
            $answer = [];
            foreach($this->roots as $category => $cparent) {
                if ($parent == $cparent) array_push($answer, $category);
            }
            return $answer;
        }
    }
}

$c = new CategoryTree;
$c->addCategory('A', null);
$c->addCategory('B', 'A');
$c->addCategory('C', 'A');
echo  $c->getChildren('A');
  1. Consider the following PHP code:
    class MilesToKmConverter
     {
         public function getMilesToKmFactor()
         {
             return 1.609;
         }
         public final function milesToKm($miles)
         {
             return $this->getMilesToKmFactor() * $miles;
         }
     }
     class NauticalMilesToKmConverter extends MilesToKmConverter
     {
         public function getMilesToKmFactor()
         {
             return 1.852;
         }
         public function printFactors()
         {
             print $this->getMilesToKmFactor() . " " . parent::getMilesToKmFactor();
         }
     }
    Select all the correct answers.
    

    answers were similar to

    1. (new MilesToKmConverter)->getMilesToKmFactor() is 1.609
    2. (new NauticalMilesToKmConverter)->getMilesToKmFactor() is 1.852
    3. (new MilesToKmConverter)-printFactors() is 1.609 1.852
    4. (new NauticalMilesToKmConverter)->printFactors() is 1.852

4. question

function sortByPriceAscending(string $jsonString) : string
{
    return '';
}

echo sortByPriceAscending('[{"name":"eggs","price":1},{"name":"coffee","price":9.99},{"name":"rice","price":4.04}]');

answer I considered

function sortByPriceAscending(string $jsonString) : string
{
    $items = json_decode($jsonString);
    arsort($items, function ($item1, $item2) {
        return $item1 <=> $item2;
    });
    foreach($items as $name => $price){
        #nothing
    }
    return json_encode($items);
}

echo sortByPriceAscending('[{"name":"eggs","price":1},{"name":"coffee","price":9.99},{"name":"rice","price":4.04}]');

answer passes 0/3 cases

function sortByPriceAscending(string $jsonString) : string
{
    $items = json_decode($jsonString);
    usort($items, function($a, $b) { return $b['price'] > $a['price'] ;});
    return json_encode($items);
}

echo sortByPriceAscending('[{"name":"eggs","price":1},{"name":"coffee","price":9.99},{"name":"rice","price":4.04}]');
  1. question ```php function changeDateFormat(array $dates) : array { return []; }

$dates = changeDateFormat( [ “2010/03/30”, “15/12/2016”, “11-15-2012”, “20130720” ] ); foreach($dates as $date) { echo $date . “\n”; }

answer passes 0/3 cases
```php
function validateDate($date, $format){
    $d = DateTime::createFromFormat($format, $date);
    return $d && $d->format($format) === $date;
}

function changeDateFormat(array $dates) : array {
    $a = [];
    foreach($dates as $date) {
        $d1 = validateDate($date, 'Y/m/d');
        $d2 = validateDate($date, 'd/m/Y');
        $d3 = validateDate($date, 'm-d-Y');
        if($d1 || $d2 || $d3) {
            array_push($a, date_format(date_create($date), 'Ymd'));
        }
        return $a;
    }
}

$dates = changeDateFormat( [ "2010/03/30", "15/12/2016", "11-15-2012", "20130720" ] );
foreach($dates as $date) {
    echo $date . "\n";
}
  1. question ```sql – Suggested testing environment: – https://www.db-fiddle.com/ with MySQL version set to 8

– Example case create statement: CREATE TABLE stock ( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, extra_data JSON );

INSERT INTO stock (extra_data) VALUES (‘{“name”: “Apple”, “total_price”: 25, “details”: {“quantity”: 5, “discounted_price”: 5}}’), (‘{“name”: “Orange”, “total_price”: 10, “details”: {“quantity”: 2, “old_price”: 5}}’), (‘{“name”: “Nail”, “total_price”: 4, “details”: {“quantity”: 3, “order”: 2}}’);

– Fill in the blanks in the following statement: SELECT extra_data-»‘__’ AS name FROM stock WHERE extra_data-»‘____’ > 2;

– Expected output (in any order): – name – —————————- – Apple – Nail

correct answer
```sql
SELECT extra_data->>'$.name' AS name FROM stock WHERE extra_data->>'$.details.quantity' > 2;
  1. question ```sql – Suggested testing environment: – http://sqlite.online/

– Example case create statement: CREATE TABLE students ( id INTEGER PRIMARY KEY, name VARCHAR(255) NOT NULL, score INTEGER NOT NULL, class INTEGER NOT NULL
);

INSERT INTO students(id, name, score, class) VALUES(1, ‘Mark’, 894, 7); INSERT INTO students(id, name, score, class) VALUES(2, ‘Bill’, 894, 7); INSERT INTO students(id, name, score, class) VALUES(3, ‘Maria’, 678, 8); INSERT INTO students(id, name, score, class) VALUES(4, ‘David’, 733, 9); INSERT INTO students(id, name, score, class) VALUES(5, ‘John’, 899, 9); INSERT INTO students(id, name, score, class) VALUES(6, ‘Rob’, 802, 9);

– Expected output (rows in any order): – name score class – ————————- – Mark 894 7
– Bill 894 7
– Maria 678 8 – John 899 9

wrong answer
```sql
select name, max(score) as score, class from students group by class;

answer passes 1/3 cases

select name,score,class from students
where score >= (SELECT score FROM students
               ORDER BY score desc
               LIMIT 1)
ORDER BY class asc;

answer sent afterwards

WITH tmp as (SELECT name, class, max(score) score
          FROM students
          GROUP BY class) 
SELECT students.name, students.score, students.class
FROM students
left join tmp
on students.class=tmp.class
where students.score = tmp.score;
  1. question ```sql – Suggested testing environment: – http://sqlite.online/

– Example case create statement: CREATE TABLE benefactors ( id INTEGER PRIMARY KEY, name VARCHAR(50) NOT NULL );

CREATE TABLE donations ( id INTEGER PRIMARY KEY, amount INTEGER NOT NULL, year INTEGER NOT NULL, benefactorId INTEGER REFERENCES benefactors(id) );

INSERT INTO benefactors(id, name) VALUES(1, ‘Phil’); INSERT INTO benefactors(id, name) VALUES(2, ‘Nicholas’); INSERT INTO benefactors(id, name) VALUES(3, ‘William’);

INSERT INTO donations(id, amount, year, benefactorId) VALUES(1, 2000, 2014, 1); INSERT INTO donations(id, amount, year, benefactorId) VALUES(2, 2800, 2015, 1); INSERT INTO donations(id, amount, year, benefactorId) VALUES(3, 900, 2015, 1); INSERT INTO donations(id, amount, year, benefactorId) VALUES(4, 1200, 2015, 2); INSERT INTO donations(id, amount, year, benefactorId) VALUES(5, 3200, 2015, null); INSERT INTO donations(id, amount, year, benefactorId) VALUES(6, 4000, 2015, null); INSERT INTO donations(id, amount, year, benefactorId) VALUES(7, 2400, 2016, 2);

– Expected output (rows in any order): – Name Amount – ——————– – Phil 3700 – Nicholas 1200 – Anonymous 7200 – William 0

return benefactor names and sum of 2015 contributions if anonymous sources (benefactorId == null), if benefactor not contributing, return 0 contribution

anonymous contribs are name ‘Anonymous’

if none in 2015, return no rows with name ‘Anonymous’

answer passes 2/4 cases
```sql
select ifnull(benefactors.name, 'Anonymous') Name,sum(donations.amount) Amount
from donations
left outer join
benefactors
ON donations.benefactorId=benefactors.id
where donations.year = 2015
group by donations.benefactorId
order by benefactors.name DESC
;
  1. question: ```sql – Suggested testing environment: – https://www.db-fiddle.com/ with MySQL version set to 8

– Example case create statement: CREATE TABLE cargo ( id INT AUTO_INCREMENT NOT NULL PRIMARY KEY, weight DOUBLE NOT NULL, declaration VARCHAR(50) NOT NULL );

INSERT INTO cargo (weight, declaration) VALUES (10.5, “toxic”), (20.2, “flamable”), (1.6, “toxic”), (12.4, “radioactive”), (30, “flamable”);

– Fill in the blanks in the following statement: SELECT declaration, ____(weight) AS weights FROM ____ GROUP BY ______;

– Expected output (in any order): – declaration weights – —————————- – flamable 20.2,30 – radioactive 12.4 – toxic 10.5,1.6

correct answer
```sql
SELECT declaration, GROUP_CONCAT(weight) AS weights FROM cargo GROUP BY declaration;
  1. Consider a large movie database with the following schema: ```sql TABLE movies id INTEGER NOT NULL PRIMARY KEY name VARCHAR(3@) NOT NULL

TABLE visitors id INTEGER NOT NULL PRIMARY KEY name VARCHAR(3@) NOT NULL

TABLE movies_visitors movieId INTEGER NOT NULL REFERENCES movies (id) visitorId INTEGER NOT NULL REFERENCES visitors (id) PRIMARY KEY (movielId, visitorId)

Select all queries that return movies having at least the average number of visitors. For example, if there are three movies, A, B and C, with 1, 5 and 6 visitors, respectively, the average number of visitors is (1+5+6)/3=4 and the query should return only movies B and C.

1. `SELECT id, COUNT(*) FROM movies JOIN movies_visitors ON movield = id GROUP BY id WHERE COUNT(*) >= ((SELECT COUNT(*) FROM movies_visitors) * 1.0 / (SELECT COUNT(*) FROM movies));`
2. `SELECT id, COUNT(*) FROM movies LEFT JOIN movies_visitors ON movield = id GROUP BY id HAVING COUNT(*) >= AVG(COUNT(*));`
3. `SELECT movield, COUNT(*) FROM movies_visitors GROUP BY movield HAVING COUNT(*) >= ((SELECT COUNT(*) FROM movies_visitors)* 1.0 / (SELECT COUNT(*) FROM movies));`
4. `SELECT id,COUNT(*) FROM movies JOIN movies_visitors ON movieId = id GROUP BY id HAVING_COUNT(*)>=((SELECTION COUNT(*) FROM movies_visitors) * 1.0 / (SELECT COUNT(*) FROM movies));`

11. rewrite CSS so header is 80% width of parent, section is 80% of width of parent plus value of `--extra_Width` CSS var

both question and correct answer
```htm
<!DOCTYPE html>
<html>
  <head>
    <title>Addition</title>
	<style>
      :root {
        --extraWidth: 10px;
      }
	  /* Write your CSS solution here */
header{width:80%;}
section{width:calc(80% + var(--extraWidth));}
	</style>
  </head>
  <body>
    <article>
      <header>
        <h1>Addition</h1>
      </header>
      <section>
        <p>The addition of two numbers is the total amount of those quantities combined.</p>
      </section>
    </article>
  </body>
</html>
  1. git commands to create branch matrix, insert file matrix.cpp, merge back to branch master

correct answers

git checkout -b matrix
git checkout matrix
...
git checkout master
git merge matrix

I publish freely as they declined my candidacy afterwards and I signed no NDA.