Help language development. Donate to The Perl Foundation

Game::Entities zef:jjatria last updated on 2021-11-14

t/sorting.t
#!/usr/bin/env raku

use Test;
use Game::Entities;

class A { has $.val }
class B { has $.val }
class C { has $.val }

for (
    *.val,                   # Sorting with single argument
    { $^a.val <=> $^b.val }, # Sorting with two arguments
) -> $comparator {
    $_ = Game::Entities.new;

    subtest "Comparator with arity { $comparator.count }" => {
        my @shuffled = ( 1 .. 30 ).pick: *;

        for ( ^@shuffled.elems ) -> $i {
            my $guid = .create;
            .add( $guid, A.new: val => @shuffled[$i] );
            .add( $guid, B.new: val => @shuffled[$i] ) if $i %% 2;
            .add( $guid, C.new: val => @shuffled[$i] ) if $i %% 3;
        }

        .sort: B, $comparator; # Sort B
        .sort: A, B;           # Sort A according to B
        .sort: C, B;           # Sort C according to B

        my @a = .view(A).components.map: *».val;
        my @b = .view(B).components.map: *».val;
        my @c = .view(C).components.map: *».val;

        # The component pool for B should be sorted
        is-deeply @b, @b.sort.Array,
            'Sorted component pool numerically';

        # Since B is a subset of A, all of the elements in B should be
        # in A, and they should all come first in the same order as in B.
        # The order of the rest of the elements does not matter.
        is-deeply @a[ ^@b.elems ].Array, @b,
            'Sorted component pool with subset';

        # Since B is a superset of C, the shared elements between the two
        # should come first and be sorted according to B.
        # The order of the rest of the elements does not matter.
        is-deeply @c.grep( * ∈ @b ), ( @b ∩ @c ).sort».key,
            'Sorted component pool with superset';
    }
}

done-testing;