2 Module : Gargantext.Core.Text.List.Social
4 Copyright : (c) CNRS, 2018-Present
5 License : AGPL + CECILL v3
6 Maintainer : team@gargantext.org
7 Stability : experimental
11 module Gargantext.Core.Text.List.Social
15 import Gargantext.Core.Types.Individu
16 import Gargantext.Database.Admin.Config
17 import Gargantext.Database.Admin.Types.Node
18 import Gargantext.Database.Prelude
19 import Gargantext.Database.Query.Table.Node.Error
20 import Gargantext.Database.Query.Tree
21 import Gargantext.Database.Query.Tree.Root (getRootId)
22 import Gargantext.Prelude
25 import Data.Maybe (fromMaybe)
28 import Data.Text (Text)
29 import Gargantext.API.Ngrams.Tools -- (getListNgrams)
30 import Gargantext.API.Ngrams.Types
31 import Gargantext.Core.Types.Main
32 import Gargantext.Database.Schema.Ngrams
33 import qualified Data.List as List
34 import qualified Data.Map as Map
35 import qualified Data.Set as Set
38 flowSocialList :: ( RepoCmdM env err m
43 => User -> NgramsType -> Set Text
44 -> m (Map ListType (Set Text))
45 flowSocialList user nt ngrams' = do
46 privateLists <- flowSocialListByMode Private user nt ngrams'
47 printDebug "* privateLists *: \n" privateLists
48 sharedLists <- flowSocialListByMode Shared user nt (termsByList CandidateTerm privateLists)
49 printDebug "* socialLists *: \n" sharedLists
52 pure $ Map.fromList [ (MapTerm, termsByList MapTerm privateLists
53 <> termsByList MapTerm sharedLists
55 , (StopTerm, termsByList StopTerm privateLists
56 <> termsByList StopTerm sharedLists
58 , (CandidateTerm, termsByList CandidateTerm sharedLists)
62 termsByList :: ListType -> (Map (Maybe ListType) (Set Text)) -> Set Text
63 termsByList CandidateTerm m = Set.unions
64 $ map (\lt -> fromMaybe Set.empty $ Map.lookup lt m)
65 [ Nothing, Just CandidateTerm ]
67 fromMaybe Set.empty $ Map.lookup (Just l) m
71 flowSocialListByMode :: ( RepoCmdM env err m
76 => NodeMode -> User -> NgramsType -> Set Text
77 -> m (Map (Maybe ListType) (Set Text))
78 flowSocialListByMode mode user nt ngrams' = do
79 listIds <- findListsId mode user
81 [] -> pure $ Map.fromList [(Nothing, ngrams')]
83 counts <- countFilterList ngrams' nt listIds Map.empty
84 printDebug "flowSocialListByMode counts" counts
85 pure $ toSocialList counts ngrams'
87 ---------------------------------------------------------------------------
88 -- TODO: maybe use social groups too
89 toSocialList :: Map Text (Map ListType Int)
91 -> Map (Maybe ListType) (Set Text)
92 toSocialList m = Map.fromListWith (<>)
94 . Set.map (toSocialList1 m)
96 -- | TODO what if equality ?
97 -- choice depends on Ord instance of ListType
98 -- for now : data ListType = StopTerm | CandidateTerm | MapTerm
99 -- means MapTerm > CandidateTerm > StopTerm in case of equality of counts
100 -- (we minimize errors on MapTerms if doubt)
101 toSocialList1 :: Map Text (Map ListType Int)
103 -> (Maybe ListType, Set Text)
104 toSocialList1 m t = case Map.lookup t m of
105 Nothing -> (Nothing, Set.singleton t)
106 Just m' -> ( (fst . fst) <$> Map.maxViewWithKey m'
110 ---------------------------------------------------------------------------
111 -- | [ListId] does not merge the lists (it is for Master and User lists
112 -- here we need UserList only
113 countFilterList :: RepoCmdM env err m
114 => Set Text -> NgramsType -> [ListId]
115 -> Map Text (Map ListType Int)
116 -> m (Map Text (Map ListType Int))
117 countFilterList st nt ls input =
118 foldM' (\m l -> countFilterList' st nt [l] m) input ls
121 countFilterList' :: RepoCmdM env err m
122 => Set Text -> NgramsType -> [ListId]
123 -> Map Text (Map ListType Int)
124 -> m (Map Text (Map ListType Int))
125 countFilterList' st nt ls input = do
126 ml <- toMapTextListType <$> getListNgrams ls nt
127 printDebug "countFilterList'" ml
128 pure $ Set.foldl' (\m t -> countList t ml m) input st
130 ---------------------------------------------------------------------------
131 -- FIXME children have to herit the ListType of the parent
132 toMapTextListType :: Map Text NgramsRepoElement -> Map Text ListType
133 toMapTextListType m = Map.fromListWith (<>)
138 listOf :: Map Text NgramsRepoElement -> NgramsRepoElement -> ListType
139 listOf m ng = case _nre_parent ng of
140 Nothing -> _nre_list ng
141 Just p -> case Map.lookup (unNgramsTerm p) m of
142 Nothing -> CandidateTerm -- Should Not happen
143 Just ng' -> listOf m ng'
145 toList :: Map Text NgramsRepoElement -> (Text, NgramsRepoElement) -> [(Text, ListType)]
146 toList m (t, nre@(NgramsRepoElement _ _ _ _ (MSet children))) =
147 List.zip terms (List.cycle [lt'])
150 -- <> maybe [] (\n -> [unNgramsTerm n]) root
151 -- <> maybe [] (\n -> [unNgramsTerm n]) parent
152 <> (map unNgramsTerm $ Map.keys children)
155 ---------------------------------------------------------------------------
158 -> Map Text (Map ListType Int)
159 -> Map Text (Map ListType Int)
160 countList t m input = case Map.lookup t m of
162 Just l -> Map.alter addList t input
164 addList Nothing = Just $ addCount l Map.empty
165 addList (Just lm) = Just $ addCount l lm
167 addCount :: ListType -> Map ListType Int -> Map ListType Int
168 addCount l m = Map.alter plus l m
170 plus Nothing = Just 1
171 plus (Just x) = Just $ x + 1
173 ------------------------------------------------------------------------
174 findListsId :: (HasNodeError err, HasTreeError err)
175 => NodeMode -> User -> Cmd err [NodeId]
176 findListsId mode u = do
178 ns <- map _dt_nodeId <$> filter (\n -> _dt_typeId n == nodeTypeId NodeList)
179 <$> findNodes' mode r
180 printDebug "findListsIds" ns
183 commonNodes:: [NodeType]
184 commonNodes = [NodeFolder, NodeCorpus, NodeList]
186 findNodes' :: HasTreeError err
187 => NodeMode -> RootId
188 -> Cmd err [DbTreeNode]
189 findNodes' Private r = findNodes Private r $ [NodeFolderPrivate] <> commonNodes
190 findNodes' Shared r = findNodes Shared r $ [NodeFolderShared ] <> commonNodes
191 findNodes' Public r = findNodes Public r $ [NodeFolderPublic ] <> commonNodes