Completed
Push — master ( 70622d...3359b7 )
by Seth
04:38
created

Relevance::add()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 5
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 2
1
<?php
2
3
namespace smtech\StMarksSearch;
4
5
use JsonSerializable;
6
7
/**
8
 * Description of a search result's relevance, with rationales
9
 *
10
 * @author Seth Battis <[email protected]>
11
 */
12
class Relevance implements JsonSerializable
13
{
14
    const EXACT_MATCH = 5;
15
16
    /**
17
     * Relevance score
18
     *
19
     * Ideally in a range from 0-10, with 5 indicating a fundamentally useful
20
     * result.
21
     *
22
     * @var float
23
     */
24
    private $score;
25
26
    /**
27
     * A list of rationales indicating how the relevance score was generated.
28
     *
29
     * @var string[]
30
     */
31
    private $rationales = [];
32
33
    /**
34
     * Construct a Relevance object
35
     *
36
     * @param float $score (Optional, defaults to 0.0)
37
     * @param string $rationale (Optional, defaults to `"Base value"` if
38
     *                          `$score` is non-zero`)
39
     */
40
    public function __construct($score = 0.0, $rationale = "Base value")
41
    {
42
        $this->score = $score;
43
        if ($score > 0) {
44
            $this->rationales[] = "$score: $rationale";
45
        }
46
    }
47
48
    /**
49
     * Add to the relevance of a score
50
     *
51
     * Or, one presumes, subtract, if `$scoreIncrement` is negative!
52
     *
53
     * @param float $scoreIncrement
54
     * @param string $rationale Rationale for this particular increment
55
     */
56
    public function add($scoreIncrement, $rationale)
57
    {
58
        $this->score += $scoreIncrement;
59
        $this->rationales[] = round($scoreIncrement, 2) . ": $rationale";
60
    }
61
62
    /**
63
     * Relevance score (ideally 0-10, with 5 indicating a fundamentally useful
64
     * result)
65
     *
66
     * @return float
67
     */
68
    public function getScore()
69
    {
70
        return $this->score;
71
    }
72
73
    /**
74
     * List of rationale's for how the relevance score was calculated
75
     *
76
     * @param  string $separator (Optional, defaults to `', '`)
77
     * @return string List of scoring rationales
78
     */
79
    public function getRationale($separator = ', ')
80
    {
81
        return implode($separator, $this->rationales);
82
    }
83
84
    /**
85
     * Calculate what proportion of the `$haystack` is made up of `$needle`
86
     *
87
     * For example `Go Dog Go!` is 40% `Go`, `Hello World` is 100% `Hello World`
88
     *
89
     * @param string $haystack
90
     * @param string $needle
91
     * @return float
92
     */
93
    public static function stringProportion($haystack, $needle)
94
    {
95
        if (preg_match("/$needle/i", $haystack, $matches) !== 1) {
96
            return 0.0;
97
        } else {
98
            return self::EXACT_MATCH * strlen($needle) * count($matches) / strlen($haystack);
99
        }
100
    }
101
102
    public function jsonSerialize()
103
    {
104
        return [
105
            'score' => $this->getScore(),
106
            'rationale' => $this->getRationale()
107
        ];
108
    }
109
}
110