Browse Source

Logiciel: Evolution #838: Base de connaissance

Bastien Sevajol 10 years ago
parent
commit
9487b910ce

+ 58 - 0
src/Muzich/CoreBundle/Command/MineTagsDataCommand.php View File

@@ -0,0 +1,58 @@
1
+<?php
2
+
3
+namespace Muzich\CoreBundle\Command;
4
+
5
+use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
6
+use Symfony\Component\Console\Input\InputInterface;
7
+use Symfony\Component\Console\Output\OutputInterface;
8
+use Muzich\CoreBundle\Mining\Tag\TagMiner;
9
+
10
+class MineTagsDataCommand extends ContainerAwareCommand
11
+{
12
+  
13
+  protected $sitemap_content;
14
+  protected $sitemap_urls;
15
+  protected $router;
16
+  protected $locales;
17
+  protected $siteurl_prefix;
18
+  protected $em;
19
+  
20
+  protected function configure()
21
+  {
22
+    $this
23
+      ->setName('mining:tags')
24
+      ->setDescription('Mine tags data')
25
+    ;
26
+  }
27
+  
28
+  /** @return TagMiner */
29
+  protected function getTagMiner()
30
+  {
31
+    return $this->getContainer()->get('muzich.mining.tag.miner');
32
+  }
33
+  
34
+  /** @return \Doctrine\ORM\EntityManager */
35
+  protected function getEntityManager()
36
+  {
37
+    return $this->em;
38
+  }
39
+
40
+  protected function init()
41
+  {
42
+    $this->em = $this->getContainer()->get('doctrine')->getEntityManager();
43
+  }
44
+  
45
+  protected function execute(InputInterface $input, OutputInterface $output)
46
+  {
47
+    $this->init();
48
+    
49
+    $tag_miner = $this->getTagMiner();
50
+    $user_query_builder = $this->getEntityManager()->createQueryBuilder()->from('MuzichCoreBundle:User', 'user');
51
+    $tag_miner->adaptQueryBuilderSelectorsForUser($user_query_builder, 'user');
52
+    // $user_query_builder->where en fonction des inputes etc
53
+    $this->getTagMiner()->mineTagsForUsers($user_query_builder->getQuery()->getResult());
54
+    
55
+    $output->writeln('<info>Terminé !</info>');
56
+  }
57
+  
58
+}

+ 147 - 0
src/Muzich/CoreBundle/Document/EntityTags.php View File

@@ -0,0 +1,147 @@
1
+<?php
2
+namespace Muzich\CoreBundle\Document;
3
+
4
+use Doctrine\ODM\MongoDB\Mapping\Annotations as MongoDB;
5
+
6
+/**
7
+ * @MongoDB\MappedSuperclass
8
+ */
9
+class EntityTags
10
+{
11
+  
12
+  const TYPE_USER = 'User';
13
+  const TYPE_GROUP = 'Group';
14
+  const TYPE_PLAYLIST = 'Playlist';
15
+  
16
+  /**
17
+   * @MongoDB\Id
18
+   */
19
+  protected $id;
20
+
21
+  /**
22
+   * @MongoDB\Int
23
+   * @MongoDB\Index(unique=true) 
24
+   */
25
+  protected $ref;
26
+
27
+  /**
28
+   * @MongoDB\Collection
29
+   */
30
+  protected $tags_top_1;
31
+
32
+  /**
33
+   * @MongoDB\Collection
34
+   */
35
+  protected $tags_top_2;
36
+
37
+  /**
38
+   * @MongoDB\Collection
39
+   */
40
+  protected $tags_top_3;
41
+
42
+  /**
43
+   * @MongoDB\Collection
44
+   */
45
+  protected $tags_top_5;
46
+
47
+  /**
48
+   * @MongoDB\Collection
49
+   */
50
+  protected $tags_top_10;
51
+
52
+  /**
53
+   * @MongoDB\Collection
54
+   */
55
+  protected $tags_top_25;
56
+
57
+  /**
58
+   * @MongoDB\Collection
59
+   */
60
+  protected $tags_all;
61
+
62
+  public function getId()
63
+  {
64
+    return $this->id;
65
+  }
66
+
67
+  public function getRef()
68
+  {
69
+    return $this->ref;
70
+  }
71
+
72
+  public function setRef($ref)
73
+  {
74
+    $this->ref = (int)$ref;
75
+  }
76
+
77
+  public function getTagsAll()
78
+  {
79
+    return $this->tags_all;
80
+  }
81
+  
82
+  public function setTagsAll($tags)
83
+  {
84
+    $this->tags_all = $tags;
85
+  }
86
+  
87
+  public function setTagsTop1($tags)
88
+  {
89
+    $this->tags_top_1 = $tags;
90
+  }
91
+  
92
+  public function getTagsTop1()
93
+  {
94
+    return $this->tags_top_1;
95
+  }
96
+  
97
+  public function setTagsTop2($tags)
98
+  {
99
+    $this->tags_top_2 = $tags;
100
+  }
101
+  
102
+  public function getTagsTop2()
103
+  {
104
+    return $this->tags_top_2;
105
+  }
106
+  
107
+  public function setTagsTop3($tags)
108
+  {
109
+    $this->tags_top_3 = $tags;
110
+  }
111
+  
112
+  public function getTagsTop3()
113
+  {
114
+    return $this->tags_top_3;
115
+  }
116
+  
117
+  public function setTagsTop5($tags)
118
+  {
119
+    $this->tags_top_5 = $tags;
120
+  }
121
+  
122
+  public function getTagsTop5()
123
+  {
124
+    return $this->tags_top_5;
125
+  }
126
+  
127
+  public function setTagsTop10($tags)
128
+  {
129
+    $this->tags_top_10 = $tags;
130
+  }
131
+  
132
+  public function getTagsTop10()
133
+  {
134
+    return $this->tags_top_10;
135
+  }
136
+  
137
+  public function setTagsTop25($tags)
138
+  {
139
+    $this->tags_top_25 = $tags;
140
+  }
141
+  
142
+  public function getTagsTop25()
143
+  {
144
+    return $this->tags_top_25;
145
+  }
146
+  
147
+}

+ 13 - 0
src/Muzich/CoreBundle/Document/GroupTags.php View File

@@ -0,0 +1,13 @@
1
+<?php
2
+namespace Muzich\CoreBundle\Document;
3
+
4
+use Doctrine\ODM\MongoDB\Mapping\Annotations as MongoDB;
5
+use Muzich\CoreBundle\Document\EntityTags;
6
+
7
+/**
8
+ * @MongoDB\Document
9
+ */
10
+class GroupTags extends EntityTags
11
+{
12
+
13
+}

+ 13 - 0
src/Muzich/CoreBundle/Document/PlaylistTags.php View File

@@ -0,0 +1,13 @@
1
+<?php
2
+namespace Muzich\CoreBundle\Document;
3
+
4
+use Doctrine\ODM\MongoDB\Mapping\Annotations as MongoDB;
5
+use Muzich\CoreBundle\Document\EntityTags;
6
+
7
+/**
8
+ * @MongoDB\Document
9
+ */
10
+class PlaylistTags extends EntityTags
11
+{
12
+
13
+}

+ 58 - 0
src/Muzich/CoreBundle/Document/UserTags.php View File

@@ -0,0 +1,58 @@
1
+<?php
2
+namespace Muzich\CoreBundle\Document;
3
+
4
+use Doctrine\ODM\MongoDB\Mapping\Annotations as MongoDB;
5
+use Muzich\CoreBundle\Document\EntityTags;
6
+
7
+/**
8
+ * @MongoDB\Document
9
+ */
10
+class UserTags extends EntityTags
11
+{
12
+
13
+  /**
14
+   * @MongoDB\Hash
15
+   */
16
+  protected $element_diffusion_tags;
17
+
18
+  /**
19
+   * @MongoDB\Hash
20
+   */
21
+  protected $element_favorite_tags;
22
+
23
+  /**
24
+   * @MongoDB\Hash
25
+   */
26
+  protected $element_playlist_tags;
27
+  
28
+  public function getElementDiffusionTags()
29
+  {
30
+    return $this->element_diffusion_tags;
31
+  }
32
+  
33
+  public function setElementDiffusionTags($tags)
34
+  {
35
+    $this->element_diffusion_tags = $tags;
36
+  }
37
+  
38
+  public function getElementFavoriteTags()
39
+  {
40
+    return $this->element_favorite_tags;
41
+  }
42
+  
43
+  public function setElementFavoriteTags($tags)
44
+  {
45
+    $this->element_favorite_tags = $tags;
46
+  }
47
+  
48
+  public function getElementPlaylistTags()
49
+  {
50
+    return $this->element_playlist_tags;
51
+  }
52
+  
53
+  public function setElementPlaylistTags($tags)
54
+  {
55
+    $this->element_playlist_tags = $tags;
56
+  }
57
+  
58
+}

+ 27 - 0
src/Muzich/CoreBundle/Entity/User.php View File

@@ -375,6 +375,20 @@ class User extends BaseUser
375 375
   {
376 376
     return $this->elements_favorites;
377 377
   }
378
+  
379
+  public function getElementsFavoritesElements()
380
+  {
381
+    if (!$this->elements_favorites)
382
+      return new ArrayCollection();
383
+    
384
+    $elements = array();
385
+    foreach ($this->elements_favorites as $element_favorite)
386
+    {
387
+      $elements[] = $element_favorite->getElement();
388
+    }
389
+    
390
+    return $elements;
391
+  }
378 392
 
379 393
   /**
380 394
    * Add elements
@@ -904,6 +918,19 @@ class User extends BaseUser
904 918
     return json_decode($this->tags_favorites_quick, true);
905 919
   }
906 920
   
921
+  public function getTagsFavoritesQuickIds()
922
+  {
923
+    $tags_favorites_ids = array();
924
+    $tags_favorites_data = $this->getTagsFavoritesQuick();
925
+    
926
+    foreach ($tags_favorites_data as $tag_id => $tag_name)
927
+    {
928
+      $tags_favorites_ids[] = $tag_id;
929
+    }
930
+    
931
+    return $tags_favorites_ids;
932
+  }
933
+  
907 934
   /**
908 935
    * 
909 936
    * @param array $tags_favorites_quick (id => name)

+ 19 - 0
src/Muzich/CoreBundle/Managers/PlaylistManager.php View File

@@ -255,6 +255,25 @@ class PlaylistManager
255 255
       ->findById($playlist->getElementsIds());
256 256
   }
257 257
   
258
+  public function getElementsOfPlaylists($playlists)
259
+  {
260
+    $elements_ids = array();
261
+    
262
+    foreach ($playlists as $playlist)
263
+    {
264
+      foreach ($playlist->getElementsIds() as $element_id)
265
+      {
266
+        $elements_ids[] = $element_id;
267
+      }
268
+    }
269
+    $elements_ids = array_unique($elements_ids);
270
+    if ($elements_ids)
271
+      return $this->entity_manager->getRepository('MuzichCoreBundle:Element')
272
+      ->findById($elements_ids);
273
+    
274
+    return array();
275
+  }
276
+  
258 277
   public function addPrivateLinks(Playlist $playlist, User $user, $links, Container $container)
259 278
   {
260 279
     // Pour le moment on le fait ici car le ElementManager est mal pensé.

+ 219 - 0
src/Muzich/CoreBundle/Mining/Tag/TagMiner.php View File

@@ -0,0 +1,219 @@
1
+<?php
2
+namespace Muzich\CoreBundle\Mining\Tag;
3
+
4
+use Doctrine\ORM\EntityManager;
5
+use Doctrine\Bundle\MongoDBBundle\ManagerRegistry as MongoManagerRegistry;
6
+use Doctrine\ODM\MongoDB\DocumentRepository;
7
+use Doctrine\ODM\MongoDB\DocumentManager;
8
+use Muzich\CoreBundle\Document\EntityTags;
9
+use Muzich\CoreBundle\Document\UserTags;
10
+use Muzich\CoreBundle\Document\GroupTags;
11
+use Muzich\CoreBundle\Document\PlaylistTags;
12
+use Doctrine\ORM\QueryBuilder;
13
+use Muzich\CoreBundle\lib\Tag as TagOrderer;
14
+use Muzich\CoreBundle\lib\TagScorer;
15
+use Muzich\CoreBundle\Entity\User;
16
+use Muzich\CoreBundle\Managers\PlaylistManager;
17
+
18
+class TagMiner
19
+{
20
+  
21
+  protected $doctrine_entity_manager;
22
+  protected $mongo_manager_registry;
23
+  protected $tag_scorer;
24
+  protected $tag_orderer;
25
+  
26
+  public function __construct(EntityManager $doctrine_entity_manager, MongoManagerRegistry $mongo_manager_registry)
27
+  {
28
+    $this->doctrine_entity_manager = $doctrine_entity_manager;
29
+    $this->mongo_manager_registry = $mongo_manager_registry;
30
+    $this->tag_scorer = new TagScorer();
31
+    $this->tag_orderer = new TagOrderer();
32
+  }
33
+  
34
+  /** @return EntityManager */
35
+  protected function getDoctrineEntityManager()
36
+  {
37
+    return $this->doctrine_entity_manager;
38
+  }
39
+  
40
+  /** @return DocumentRepository */
41
+  protected function getMongoRepository($repository)
42
+  {
43
+    return $this->mongo_manager_registry->getRepository($repository);
44
+  }
45
+  
46
+  /** @return DocumentManager */
47
+  protected function getMongoManager()
48
+  {
49
+    return $this->mongo_manager_registry->getManager();
50
+  }
51
+  
52
+  /** @return TagScorer */
53
+  protected function getTagsScorer()
54
+  {
55
+    return $this->tag_scorer;
56
+  }
57
+  
58
+  /** @return TagOrderer */
59
+  protected function getTagOrderer()
60
+  {
61
+    return $this->tag_orderer;
62
+  }
63
+  
64
+  /** 
65
+   * @param QueryBuilder $query_builder
66
+   * @param string $user_alias
67
+   */
68
+  public function adaptQueryBuilderSelectorsForUser(QueryBuilder $query_builder, $user_alias = 'user')
69
+  {
70
+    // Adapt query builder to necessary data in mining
71
+    $query_builder->leftJoin($user_alias.'.elements', 'element_owned');
72
+    $query_builder->leftJoin('element_owned.tags', 'element_owned_tags');
73
+    
74
+    $query_builder->leftJoin($user_alias.'.elements_favorites', 'element_favorite');
75
+    $query_builder->leftJoin('element_favorite.element', 'element_favorite_element');
76
+    
77
+    $query_builder->select($user_alias.', element_owned, element_owned_tags, element_favorite');
78
+    
79
+  }
80
+  
81
+  /**
82
+   * @param array $users
83
+   */
84
+  public function mineTagsForUsers($users)
85
+  {
86
+    foreach ($users as $user)
87
+    {
88
+      $user_tags = $this->getEntityTagsDocument($user->getId(), EntityTags::TYPE_USER);
89
+      
90
+      $this->scoreUserDiffusionsTags($user_tags, $user);
91
+      $this->scoreUserFavoritesTags($user_tags, $user);
92
+      $this->scoreUserPlaylistsTags($user_tags, $user);
93
+      $this->scoreUserTags($user_tags, $user);
94
+      $this->determineTagsTops($user_tags);
95
+      
96
+      $this->getMongoManager()->persist($user_tags);
97
+    }
98
+    
99
+    $this->getMongoManager()->flush();
100
+  }
101
+  
102
+  /** @return EntityTags */
103
+  protected function getEntityTagsDocument($ref, $type)
104
+  {
105
+    if (!($user_tags = $this->getMongoManager()->createQueryBuilder('MuzichCoreBundle:'.$type.'Tags')
106
+      ->field('ref')->equals((int)$ref)
107
+      ->getQuery()->getSingleResult()
108
+    ))
109
+    {
110
+      $user_tags = $this->getObjectTypeTags($type);
111
+      $user_tags->setRef($ref);
112
+    }
113
+    
114
+    return $user_tags;
115
+  }
116
+  
117
+  /** @return EntityTags */
118
+  protected function getObjectTypeTags($type)
119
+  {
120
+    switch ($type)
121
+    {
122
+      case EntityTags::TYPE_USER:
123
+        return new UserTags();
124
+      break;
125
+      case EntityTags::TYPE_GROUP:
126
+        return new GroupTags();
127
+      break;
128
+      case EntityTags::TYPE_PLAYLIST:
129
+        return new PlaylistTags();
130
+      break;
131
+    }
132
+  }
133
+  
134
+  protected function scoreUserDiffusionsTags(EntityTags $user_tags, User $user)
135
+  {
136
+    $tags_ids_ordereds = $this->getTagOrderer()->getOrderedTagsWithElements($user->getElements());
137
+    $scoreds_tags_ids = $this->getTagsScorer()->scoreOrderedsTagsIds($tags_ids_ordereds);
138
+    $user_tags->setElementDiffusionTags($scoreds_tags_ids);
139
+  }
140
+  
141
+  protected function scoreUserFavoritesTags(EntityTags $user_tags, User $user)
142
+  {
143
+    $tags_ids_ordereds = $this->getTagOrderer()->getOrderedTagsWithElements($user->getElementsFavoritesElements());
144
+    $scoreds_tags_ids = $this->getTagsScorer()->scoreOrderedsTagsIds($tags_ids_ordereds);
145
+    $user_tags->setElementFavoriteTags($scoreds_tags_ids);
146
+  }
147
+  
148
+  protected function scoreUserPlaylistsTags(EntityTags $user_tags, User $user)
149
+  {
150
+    $playlist_manager = new PlaylistManager($this->getDoctrineEntityManager());
151
+    $tags_ids_ordereds = $this->getTagOrderer()->getOrderedTagsWithElements($playlist_manager->getElementsOfPlaylists($this->getUserPlaylists($user)));
152
+    $scoreds_tags_ids = $this->getTagsScorer()->scoreOrderedsTagsIds($tags_ids_ordereds);
153
+    $user_tags->setElementPlaylistTags($scoreds_tags_ids);
154
+  }
155
+  
156
+  protected function getUserPlaylists(User $user)
157
+  {
158
+    $playlists = $user->getPlaylistsOwneds();
159
+    foreach ($user->getPickedsPlaylists() as $picked_playlist)
160
+    {
161
+      $found = false;
162
+      foreach ($playlists as $playlist)
163
+      {
164
+        if ($playlist->getId() == $picked_playlist->getId())
165
+        {
166
+          $found = true;
167
+        }
168
+      }
169
+      
170
+      if (!$found)
171
+        $playlists[] = $picked_playlist;
172
+    }
173
+    
174
+    return $playlists;
175
+  }
176
+  
177
+  protected function scoreUserTags(EntityTags $user_tags, User $user)
178
+  {
179
+    $all_tags_ordered = $this->getTagsScorer()->scoreEntireOrderedTagsIds(array(
180
+      $user_tags->getElementDiffusionTags(),
181
+      $user_tags->getElementFavoriteTags(),
182
+      $user_tags->getElementPlaylistTags()
183
+    ), $user->getTagsFavoritesQuickIds());
184
+    
185
+    $user_tags->setTagsAll($all_tags_ordered);
186
+  }
187
+  
188
+  protected function determineTagsTops(EntityTags $user_tags)
189
+  {
190
+    $user_tags->setTagsTop1($this->getTopTagsRange($user_tags->getTagsAll(), 1));
191
+    $user_tags->setTagsTop2($this->getTopTagsRange($user_tags->getTagsAll(), 2));
192
+    $user_tags->setTagsTop3($this->getTopTagsRange($user_tags->getTagsAll(), 3));
193
+    $user_tags->setTagsTop5($this->getTopTagsRange($user_tags->getTagsAll(), 5));
194
+    $user_tags->setTagsTop10($this->getTopTagsRange($user_tags->getTagsAll(), 10));
195
+    $user_tags->setTagsTop25($this->getTopTagsRange($user_tags->getTagsAll(), 25));
196
+  }
197
+  
198
+  protected function getTopTagsRange($tags, $range_end)
199
+  {
200
+    $tags_top = array();
201
+    if ($range_end <= count($tags))
202
+    {
203
+      $max = $range_end;
204
+    }
205
+    else
206
+    {
207
+      $max = count($tags);
208
+    }
209
+      
210
+    for ($index = 0; $index <= $max-1; $index++)
211
+    {
212
+      $tags_top[] = $tags[$index];
213
+    }
214
+    
215
+    
216
+    return $tags_top;
217
+  }
218
+  
219
+}

+ 56 - 0
src/Muzich/CoreBundle/lib/TagScorer.php View File

@@ -0,0 +1,56 @@
1
+<?php
2
+
3
+namespace Muzich\CoreBundle\lib;
4
+
5
+class TagScorer
6
+{
7
+  
8
+  public function scoreOrderedsTagsIds($ordered_tags)
9
+  {
10
+    $tags_ordered_by_score = array();
11
+    $score_max = count($ordered_tags);
12
+    
13
+    foreach ($ordered_tags as $tag_id)
14
+    {
15
+      $tags_ordered_by_score[(int)$score_max] = $tag_id;
16
+      $score_max -= 1;
17
+    }
18
+    
19
+    return $tags_ordered_by_score;
20
+  }
21
+  
22
+  public function scoreEntireOrderedTagsIds($ordereds_elements_tags_ids, $favoriteds_tags)
23
+  {
24
+    $tags_score = array();
25
+    
26
+    foreach ($ordereds_elements_tags_ids as $ordereds_tags_ids)
27
+    {
28
+      foreach ($ordereds_tags_ids as $score_tag => $tag_id)
29
+      {
30
+        if (!array_key_exists($tag_id, $tags_score))
31
+          $tags_score[$tag_id] = 0;
32
+        
33
+        $tags_score[$tag_id] += $score_tag;
34
+      }
35
+    }
36
+    
37
+    foreach ($favoriteds_tags as $favorite_tag_id)
38
+    {
39
+      if (!array_key_exists($favorite_tag_id, $tags_score))
40
+        $tags_score[$favorite_tag_id] = 0;
41
+        
42
+      $tags_score[$favorite_tag_id] += 5;
43
+    }
44
+        
45
+    arsort($tags_score);
46
+    
47
+    $oredered_tags_ids_without_score = array();
48
+    foreach ($tags_score as $tag_id => $tag_score)
49
+    {
50
+      $oredered_tags_ids_without_score[] = $tag_id;
51
+    }
52
+    
53
+    return $oredered_tags_ids_without_score;
54
+  }
55
+  
56
+}