LetterLanguageManager.php 7.75 KB
Newer Older
arnaudbey's avatar
add app  
arnaudbey committed
1
2
3
4
5
<?php

namespace  MagicWordBundle\Manager\Letter;

use JMS\DiExtraBundle\Annotation as DI;
arnaudbey's avatar
arnaudbey committed
6
use LexiconBundle\Entity\Language;
arnaudbey's avatar
add app  
arnaudbey committed
7
8
9
10
11
12
13
14
15
16
17
18
19

/**
 * @DI\Service("mw_manager.letter_language")
 */
class LetterLanguageManager
{
    protected $em;

    /**
     * @DI\InjectParams({
     *      "entityManager" = @DI\Inject("doctrine.orm.entity_manager"),
     * })
     */
Arnaud Bey's avatar
WIP    
Arnaud Bey committed
20
    public function __construct($entityManager)
arnaudbey's avatar
add app  
arnaudbey committed
21
22
23
24
    {
        $this->em = $entityManager;
    }

25
    public function lottery(Language $language, $side, $debug = false)
arnaudbey's avatar
add app  
arnaudbey committed
26
    {
Arnaud Bey's avatar
WIP    
Arnaud Bey committed
27
28
29
30
31
        $fileBigrams = $language->getDirectory().DIRECTORY_SEPARATOR."bigrams.txt";
        // On crée un tableau de bigrammes
        // où chaque bigramme apparait autant de fois que son poids
        $bigrams = [];
        $lines = file($fileBigrams);
32
        $lettersFromBigrams=[];
Arnaud Bey's avatar
WIP    
Arnaud Bey committed
33
34
35
36
37
        array_shift($lines);
        foreach ($lines as $line) {
            $tab = explode("\t", $line);
            $string = $tab[0];
            $poids = $tab[3];
38
39
40
41
            $bigramLetters = preg_split('//u', $string, null, PREG_SPLIT_NO_EMPTY);
            foreach ($bigramLetters as $bigramLetter) {
                $lettersFromBigrams[$bigramLetter] = 1;
            }
Arnaud Bey's avatar
WIP    
Arnaud Bey committed
42
43
44
45
46

            for ($j = 0; $j < $poids; $j++) {
                $bigrams[] = $string;
            }
        }
47
48
49
50
        $countsBigram = array_count_values($bigrams);
        // var_dump($countsBigram);
        // die();
        // // On initialise une grille vide.
Arnaud Bey's avatar
WIP    
Arnaud Bey committed
51
52
53
54
55
        $grid = [];
        for ($i=0; $i < $side; $i++) {
            for ($j=0; $j < $side; $j++) {
                $grid[$i][$j] = null;
            }
arnaudbey's avatar
add app  
arnaudbey committed
56
57
        }

Arnaud Bey's avatar
WIP    
Arnaud Bey committed
58
        $emptySquares = $this->getEmptySquares($grid, $side);
59
        //tant qu'il reste des cases vides
Arnaud Bey's avatar
WIP    
Arnaud Bey committed
60
61
62
63
64
        while (!empty($emptySquares)) {
            $bigram = $bigrams[array_rand($bigrams)];
            $emptySquare = $emptySquares[array_rand($emptySquares)];
            $emptySquareI = $emptySquare[0];
            $emptySquareJ = $emptySquare[1];
arnaudbey's avatar
add app  
arnaudbey committed
65

Arnaud Bey's avatar
WIP    
Arnaud Bey committed
66
67
68
            $chars = preg_split('//u', $bigram, -1, PREG_SPLIT_NO_EMPTY);
            $firstLetter = $chars[0];
            $secondLetter = $chars[1];
Sylvain Hatier's avatar
Sylvain Hatier committed
69
            $flagBigram = false;
70
            // on regarde si une lettre du bigram pioché est déjà présente et qu'elle a des adjacent vide.
Sylvain Hatier's avatar
Sylvain Hatier committed
71
72
73
            for ($i=0; $i < $side; $i++) {
                for ($j=0; $j < $side; $j++) {
                    if ($grid[$i][$j] == $firstLetter) {
74
                        $ajdacentsLetterBigram = $this->getAdjacentSquares($grid, $side, [$i, $j], true);
Sylvain Hatier's avatar
Sylvain Hatier committed
75
76
77
78
79
80
81
                        if (!empty($ajdacentsLetterBigram)) {
                            $ajdacentLetterBigram = $ajdacentsLetterBigram[array_rand($ajdacentsLetterBigram)];
                            $grid[$ajdacentLetterBigram[0]][$ajdacentLetterBigram[1]] = $secondLetter;
                            $flagBigram = true;
                            break 2;
                        }
                    } elseif ($grid[$i][$j] == $secondLetter) {
82
                        $ajdacentsLetterBigram = $this->getAdjacentSquares($grid, $side, [$i, $j], true);
Sylvain Hatier's avatar
Sylvain Hatier committed
83
84
85
86
87
88
89
90
91
92
                        if (!empty($ajdacentsLetterBigram)) {
                            $ajdacentLetterBigram = $ajdacentsLetterBigram[array_rand($ajdacentsLetterBigram)];
                            $grid[$ajdacentLetterBigram[0]][$ajdacentLetterBigram[1]] = $firstLetter;
                            $flagBigram = true;
                            break 2;
                        }
                    }
                }
            }
            if (!$flagBigram) {
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
                $ajdacentEmptySquares = $this->getAdjacentSquares($grid, $side, $emptySquare, true);

                if (empty($ajdacentEmptySquares)) {
                    $ajdacentSquares = $this->getAdjacentSquares($grid, $side, $emptySquare, false);
                    $letterToScore=[];
                    foreach ($lettersFromBigrams as $key => $value) {
                        $score=0;
                        foreach ($ajdacentSquares as $ajdacentSquare) {
                            $letter = $grid[$ajdacentSquare[0]][$ajdacentSquare[1]];
                            if (isset($countsBigram[$letter.$key])) {
                                $score += $countsBigram[$letter.$key];
                            } elseif (isset($countsBigram[$key.$letter])) {
                                $score += $countsBigram[$key.$letter];
                            }
                        }
                        $letterToScore[$key] = $score;
                    }
                    arsort($letterToScore);
                    reset($letterToScore);
                    $bestLetter = key($letterToScore);
                    $grid[$emptySquareI][$emptySquareJ] = $bestLetter;
                } else {
                    $randomAdjacent = $ajdacentEmptySquares[array_rand($ajdacentEmptySquares)];
                    $grid[$emptySquareI][$emptySquareJ] = $firstLetter;
                    $grid[$randomAdjacent[0]][$randomAdjacent[1]] = $secondLetter;
                }
Sylvain Hatier's avatar
Sylvain Hatier committed
119
            }
Arnaud Bey's avatar
WIP    
Arnaud Bey committed
120
121
122
123
124
125
126
            $emptySquares = $this->getEmptySquares($grid, $side);
        }

        $letters = [];
        for ($i=0; $i < $side; $i++) {
            for ($j=0; $j < $side; $j++) {
                $letters[] = $grid[$i][$j];
arnaudbey's avatar
add app  
arnaudbey committed
127
128
129
130
131
            }
        }
        return $letters;
    }

132
    private function getAdjacentSquares($grid, $side, $square, $returnEmpty = true)
arnaudbey's avatar
add app  
arnaudbey committed
133
    {
Arnaud Bey's avatar
WIP    
Arnaud Bey committed
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
        $emptyAdjacentSquares = [];
        $i = $square[0];
        $j = $square[1];

        $left = $i - 1;
        $right = $i + 1;
        $top = $j - 1;
        $bottom = $j + 1;

        $lookLeft = ($left >= 0) ? true : false;
        $lookTop = ($top >= 0) ? true : false;
        $lookRight = ($right < $side) ? true : false;
        $lookBottom = ($bottom < $side) ? true : false;

        if ($lookTop) {
            if ($lookLeft && $grid[$top][$left] === null) {
                $emptyAdjacentSquares[] = [$top, $left];
151
152
            } elseif ($lookLeft) {
                $adjacentSquares[] = [$top, $left];
Arnaud Bey's avatar
WIP    
Arnaud Bey committed
153
154
            }

155

Arnaud Bey's avatar
WIP    
Arnaud Bey committed
156
157
158
            if ($grid[$top][$j] === null) {
                $emptyAdjacentSquares[] = [$top, $j];
            }
159
            $adjacentSquares[] = [$top, $j];
Arnaud Bey's avatar
WIP    
Arnaud Bey committed
160
161
            if ($lookRight && $grid[$top][$right] === null) {
                $emptyAdjacentSquares[] = [$top, $right];
162
163
            } elseif ($lookRight) {
                $adjacentSquares[] = [$top, $right];
Arnaud Bey's avatar
WIP    
Arnaud Bey committed
164
165
166
167
168
            }
        }

        if ($lookRight && $grid[$i][$right] === null) {
            $emptyAdjacentSquares[] = [$i, $right];
169
170
        } elseif ($lookRight) {
            $adjacentSquares[] = [$i, $right];
Arnaud Bey's avatar
WIP    
Arnaud Bey committed
171
172
        }

173

Arnaud Bey's avatar
WIP    
Arnaud Bey committed
174
175
176
        if ($lookBottom) {
            if ($lookRight && $grid[$bottom][$right] === null) {
                $emptyAdjacentSquares[] = [$bottom, $right];
177
178
            } elseif ($lookRight) {
                $adjacentSquares[] = [$bottom, $right];
Arnaud Bey's avatar
WIP    
Arnaud Bey committed
179
            }
180
            $adjacentSquares[] = [$bottom, $j];
Arnaud Bey's avatar
WIP    
Arnaud Bey committed
181
182
183
184
185
            if ($grid[$bottom][$j] === null) {
                $emptyAdjacentSquares[] = [$bottom, $j];
            }
            if ($lookLeft && $grid[$bottom][$left] === null) {
                $emptyAdjacentSquares[] = [$bottom, $left];
186
187
            } elseif ($lookLeft) {
                $adjacentSquares[] = [$bottom, $left];
Arnaud Bey's avatar
WIP    
Arnaud Bey committed
188
189
190
191
192
            }
        }

        if ($lookLeft && $grid[$i][$left] === null) {
            $emptyAdjacentSquares[] = [$i, $left];
193
194
        } elseif ($lookLeft) {
            $adjacentSquares[] = [$i, $left];
Arnaud Bey's avatar
WIP    
Arnaud Bey committed
195
        }
arnaudbey's avatar
add app  
arnaudbey committed
196

197
198

        return ($returnEmpty) ? $emptyAdjacentSquares : $adjacentSquares;
arnaudbey's avatar
add app  
arnaudbey committed
199
200
    }

Arnaud Bey's avatar
WIP    
Arnaud Bey committed
201
    private function getEmptySquares($grid, $side)
arnaudbey's avatar
add app  
arnaudbey committed
202
    {
Arnaud Bey's avatar
WIP    
Arnaud Bey committed
203
204
205
206
207
208
209
210
211
        $emptySquares = [];

        for ($i=0; $i < $side; $i++) {
            for ($j=0; $j < $side; $j++) {
                if ($grid[$i][$j] === null) {
                    $emptySquares[] = [$i, $j];
                }
            }
        }
arnaudbey's avatar
add app  
arnaudbey committed
212

Arnaud Bey's avatar
WIP    
Arnaud Bey committed
213
        return $emptySquares;
arnaudbey's avatar
add app  
arnaudbey committed
214
215
    }
}