Passed
Push — main ( f4e9d2...4a4379 )
by Jesse
01:41
created

PuzzleSolverFactory::eagerStrategy()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 16
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 10
c 1
b 0
f 0
nc 3
nop 1
dl 0
loc 16
rs 9.9332
1
<?php declare(strict_types=1);
2
3
namespace Stratadox\PuzzleSolver;
4
5
use Stratadox\PuzzleSolver\SearchStrategy\BestFirstStrategyFactory;
6
use Stratadox\PuzzleSolver\SearchStrategy\BreadthFirstStrategyFactory;
7
use Stratadox\PuzzleSolver\SearchStrategy\DebugLoggerFactory;
8
use Stratadox\PuzzleSolver\SearchStrategy\DepthFirstStrategyFactory;
9
use Stratadox\PuzzleSolver\SearchStrategy\DuplicateNodeSkipperFactory;
10
use Stratadox\PuzzleSolver\SearchStrategy\SearchStrategyFactory;
11
use Stratadox\PuzzleSolver\SearchStrategy\VisitedNodeCostCheckerFactory;
12
use Stratadox\PuzzleSolver\SearchStrategy\VisitedNodeSkipperFactory;
13
use Stratadox\PuzzleSolver\SearchStrategy\WorseThanBestSolutionSkipperFactory;
14
use Stratadox\PuzzleSolver\Solver\EagerSolver;
15
use Stratadox\PuzzleSolver\Solver\LazySolver;
16
17
/**
18
 * Factory for @see PuzzleSolver
19
 *
20
 * @author Stratadox
21
 */
22
final class PuzzleSolverFactory implements SolverFactory
23
{
24
    public static function make(): self
25
    {
26
        return new self();
27
    }
28
29
    public function forAPuzzleWith(
30
        PuzzleDescription $puzzle,
31
        SearchSettings $settings
32
    ): PuzzleSolver {
33
        return $puzzle->singleSolution() ?
34
            EagerSolver::using($this->add($settings, $this->eagerStrategy($puzzle))) :
35
            LazySolver::using($this->add($settings, $this->lazyStrategy($puzzle)));
36
    }
37
38
    private function add(
39
        SearchSettings $settings,
40
        SearchStrategyFactory $strategyFactory
41
    ): SearchStrategyFactory {
42
        if (null === $settings->loggingFile()) {
43
            return $strategyFactory;
44
        }
45
        return DebugLoggerFactory::make(
46
            $settings->iterationInterval(),
47
            $strategyFactory,
48
            $settings->logSeparator(),
49
            $settings->loggingFile()
50
        );
51
    }
52
53
    /**
54
     * Retrieves the eagerStrategy, based on the current description.
55
     *
56
     * @return SearchStrategyFactory
57
     *
58
     * @todo Add more test puzzles that require a single solution, to challenge
59
     *       the assumptions currently made.
60
     */
61
    private function eagerStrategy(PuzzleDescription $puzzle): SearchStrategyFactory
62
    {
63
        if (null !== $puzzle->heuristic()) {
64
            return VisitedNodeCostCheckerFactory::using(
65
                BestFirstStrategyFactory::withHeuristic($puzzle->heuristic())
66
            );
67
        }
68
        if ($puzzle->isWeightedMoves()) {
69
            return VisitedNodeCostCheckerFactory::using(
70
                BestFirstStrategyFactory::noHeuristic()
71
            );
72
        }
73
        return VisitedNodeSkipperFactory::using(
74
            $puzzle->isExhausting() ?
75
                DepthFirstStrategyFactory::make() :
76
                BreadthFirstStrategyFactory::make()
77
        );
78
    }
79
80
    /**
81
     * Retrieves the lazyStrategy, based on the current description.
82
     *
83
     * @return SearchStrategyFactory
84
     *
85
     * @todo Add more test puzzles that require multiple solutions, to challenge
86
     *       the assumptions currently made.
87
     */
88
    private function lazyStrategy(PuzzleDescription $puzzle): SearchStrategyFactory
89
    {
90
        if ($puzzle->isExhausting()) {
91
            return VisitedNodeSkipperFactory::using(
92
                DepthFirstStrategyFactory::make()
93
            );
94
        }
95
        if ($puzzle->onlyBest()) {
96
            return WorseThanBestSolutionSkipperFactory::using(
97
                BreadthFirstStrategyFactory::make()
98
            );
99
        }
100
        return DuplicateNodeSkipperFactory::using(
101
            DepthFirstStrategyFactory::make()
102
        );
103
    }
104
}
105