2 Module : Gargantext.API.Metrics
3 Description : Server API
4 Copyright : (c) CNRS, 2017-Present
5 License : AGPL + CECILL v3
6 Maintainer : team@gargantext.org
7 Stability : experimental
14 {-# OPTIONS_GHC -fno-warn-orphans #-}
16 {-# LANGUAGE TypeOperators #-}
18 module Gargantext.API.Metrics
23 import qualified Data.Digest.Pure.MD5 as DPMD5
25 import Data.Time (UTCTime)
26 import GHC.Generics (Generic)
29 import qualified Data.Map as Map
31 import Gargantext.API.Ngrams
32 import Gargantext.API.Ngrams.NTree
33 import Gargantext.API.Prelude (GargServer)
34 import Gargantext.Core.Types (CorpusId, Limit, ListId, ListType(..))
35 import Gargantext.Database.Action.Flow
36 import qualified Gargantext.Database.Action.Metrics as Metrics
37 import Gargantext.Database.Admin.Types.Hyperdata (HyperdataList(..))
38 import Gargantext.Database.Admin.Types.Metrics (ChartMetrics(..), Metric(..), Metrics(..))
39 import Gargantext.Database.Admin.Types.Node (NodeId)
40 import Gargantext.Database.Query.Table.Node (defaultList, getNodeWith)
41 import Gargantext.Database.Query.Table.Node.Error (HasNodeError)
42 import Gargantext.Database.Query.Table.Node.UpdateOpaleye (updateHyperdata)
43 import Gargantext.Database.Prelude
44 import Gargantext.Database.Schema.Node (node_hyperdata)
45 import Gargantext.Text.Metrics (Scored(..))
46 import Gargantext.Viz.Chart
47 import Gargantext.Viz.Types
49 data HashedResponse a = HashedResponse { md5 :: Text, value :: a }
52 instance ToSchema a => ToSchema (HashedResponse a)
53 instance ToJSON a => ToJSON (HashedResponse a) where
54 toJSON = genericToJSON defaultOptions
56 constructHashedResponse :: ToJSON a => a -> HashedResponse a
57 constructHashedResponse chart = HashedResponse { md5 = md5', value = chart }
59 md5' = show $ DPMD5.md5 $ encode chart
61 -------------------------------------------------------------
62 -- | Scatter metrics API
63 type ScatterAPI = Summary "SepGen IncExc metrics"
64 :> QueryParam "list" ListId
65 :> QueryParamR "ngramsType" TabType
66 :> QueryParam "limit" Int
67 :> Get '[JSON] (HashedResponse Metrics)
68 :<|> Summary "Scatter update"
69 :> QueryParam "list" ListId
70 :> QueryParamR "ngramsType" TabType
71 :> QueryParam "limit" Int
75 :> QueryParam "list" ListId
76 :> QueryParamR "ngramsType" TabType
79 scatterApi :: NodeId -> GargServer ScatterAPI
80 scatterApi id' = getScatter id'
81 :<|> updateScatter id'
82 :<|> getScatterMD5 id'
84 getScatter :: FlowCmdM env err m =>
89 -> m (HashedResponse Metrics)
90 getScatter cId maybeListId tabType _maybeLimit = do
91 listId <- case maybeListId of
93 Nothing -> defaultList cId
94 node <- getNodeWith listId (Proxy :: Proxy HyperdataList)
95 let HyperdataList { hd_scatter = mChart } = node ^. node_hyperdata
97 chart <- case mChart of
98 Just chart -> pure chart
100 updateScatter' cId maybeListId tabType Nothing
102 pure $ constructHashedResponse chart
104 updateScatter :: FlowCmdM env err m =>
110 updateScatter cId maybeListId tabType maybeLimit = do
111 _ <- updateScatter' cId maybeListId tabType maybeLimit
114 updateScatter' :: FlowCmdM env err m =>
120 updateScatter' cId maybeListId tabType maybeLimit = do
121 (ngs', scores) <- Metrics.getMetrics cId maybeListId tabType maybeLimit
124 metrics = map (\(Scored t s1 s2) -> Metric t (log' 5 s1) (log' 2 s2) (listType t ngs')) scores
125 log' n x = 1 + (if x <= 0 then 0 else log $ (10^(n::Int)) * x)
126 listType t m = maybe (panic errorMsg) fst $ Map.lookup t m
127 errorMsg = "API.Node.metrics: key absent"
129 listId <- case maybeListId of
131 Nothing -> defaultList cId
132 node <- getNodeWith listId (Proxy :: Proxy HyperdataList)
133 let HyperdataList { hd_chart = hdc
136 , hd_tree = hdt } = node ^. node_hyperdata
137 _ <- updateHyperdata listId $ HyperdataList hdc hdl hdp (Just $ Metrics metrics) hdt
139 pure $ Metrics metrics
141 getScatterMD5 :: FlowCmdM env err m =>
146 getScatterMD5 cId maybeListId tabType = do
147 HashedResponse { md5 = md5' } <- getScatter cId maybeListId tabType Nothing
151 -------------------------------------------------------------
152 -- | Chart metrics API
153 type ChartApi = Summary " Chart API"
154 :> QueryParam "from" UTCTime
155 :> QueryParam "to" UTCTime
156 :> QueryParam "list" ListId
157 :> QueryParamR "ngramsType" TabType
158 :> Get '[JSON] (HashedResponse (ChartMetrics Histo))
159 :<|> Summary "Chart update"
160 :> QueryParam "list" ListId
161 :> QueryParamR "ngramsType" TabType
162 :> QueryParam "limit" Int
166 :> QueryParam "list" ListId
167 :> QueryParamR "ngramsType" TabType
170 chartApi :: NodeId -> GargServer ChartApi
171 chartApi id' = getChart id'
175 -- TODO add start / end
176 getChart :: FlowCmdM env err m =>
182 -> m (HashedResponse (ChartMetrics Histo))
183 getChart cId _start _end maybeListId tabType = do
184 listId <- case maybeListId of
186 Nothing -> defaultList cId
187 node <- getNodeWith listId (Proxy :: Proxy HyperdataList)
188 let HyperdataList { hd_chart = mChart } = node ^. node_hyperdata
190 chart <- case mChart of
191 Just chart -> pure chart
193 updateChart' cId maybeListId tabType Nothing
195 pure $ constructHashedResponse chart
197 updateChart :: HasNodeError err =>
203 updateChart cId maybeListId tabType maybeLimit = do
204 _ <- updateChart' cId maybeListId tabType maybeLimit
207 updateChart' :: HasNodeError err =>
212 -> Cmd err (ChartMetrics Histo)
213 updateChart' cId maybeListId _tabType _maybeLimit = do
214 listId <- case maybeListId of
216 Nothing -> defaultList cId
217 node <- getNodeWith listId (Proxy :: Proxy HyperdataList)
218 let HyperdataList { hd_list = hdl
221 , hd_tree = hdt } = node ^. node_hyperdata
223 _ <- updateHyperdata listId $ HyperdataList (Just $ ChartMetrics h) hdl hdp hds hdt
225 pure $ ChartMetrics h
228 getChartMD5 :: FlowCmdM env err m =>
233 getChartMD5 cId maybeListId tabType = do
234 HashedResponse { md5 = md5' } <- getChart cId Nothing Nothing maybeListId tabType
236 -------------------------------------------------------------
238 type PieApi = Summary "Pie Chart"
239 :> QueryParam "from" UTCTime
240 :> QueryParam "to" UTCTime
241 :> QueryParam "list" ListId
242 :> QueryParamR "ngramsType" TabType
243 :> Get '[JSON] (HashedResponse (ChartMetrics Histo))
244 :<|> Summary "Pie Chart update"
245 :> QueryParam "list" ListId
246 :> QueryParamR "ngramsType" TabType
247 :> QueryParam "limit" Int
251 :> QueryParam "list" ListId
252 :> QueryParamR "ngramsType" TabType
255 pieApi :: NodeId -> GargServer PieApi
256 pieApi id' = getPie id'
260 getPie :: FlowCmdM env err m
266 -> m (HashedResponse (ChartMetrics Histo))
267 getPie cId _start _end maybeListId tabType = do
268 listId <- case maybeListId of
270 Nothing -> defaultList cId
271 node <- getNodeWith listId (Proxy :: Proxy HyperdataList)
272 let HyperdataList { hd_pie = mChart } = node ^. node_hyperdata
274 chart <- case mChart of
275 Just chart -> pure chart
277 updatePie' cId maybeListId tabType Nothing
279 pure $ constructHashedResponse chart
281 updatePie :: FlowCmdM env err m =>
287 updatePie cId maybeListId tabType maybeLimit = do
288 _ <- updatePie' cId maybeListId tabType maybeLimit
291 updatePie' :: FlowCmdM env err m =>
296 -> m (ChartMetrics Histo)
297 updatePie' cId maybeListId tabType _maybeLimit = do
298 listId <- case maybeListId of
300 Nothing -> defaultList cId
301 node <- getNodeWith listId (Proxy :: Proxy HyperdataList)
302 let HyperdataList { hd_chart = hdc
305 , hd_tree = hdt } = node ^. node_hyperdata
307 p <- pieData cId (ngramsTypeFromTabType tabType) MapTerm
308 _ <- updateHyperdata listId $ HyperdataList hdc hdl (Just $ ChartMetrics p) hds hdt
310 pure $ ChartMetrics p
312 getPieMD5 :: FlowCmdM env err m =>
317 getPieMD5 cId maybeListId tabType = do
318 HashedResponse { md5 = md5' } <- getPie cId Nothing Nothing maybeListId tabType
320 -------------------------------------------------------------
321 -- | Tree metrics API
323 type TreeApi = Summary " Tree API"
324 :> QueryParam "from" UTCTime
325 :> QueryParam "to" UTCTime
326 :> QueryParam "list" ListId
327 :> QueryParamR "ngramsType" TabType
328 :> QueryParamR "listType" ListType
329 :> Get '[JSON] (HashedResponse (ChartMetrics [MyTree]))
330 :<|> Summary "Tree Chart update"
331 :> QueryParam "list" ListId
332 :> QueryParamR "ngramsType" TabType
333 :> QueryParamR "listType" ListType
337 :> QueryParam "list" ListId
338 :> QueryParamR "ngramsType" TabType
339 :> QueryParamR "listType" ListType
342 -- Depending on the Type of the Node, we could post
343 -- New documents for a corpus
344 -- New map list terms
345 -- :<|> "process" :> MultipartForm MultipartData :> Post '[JSON] Text
347 treeApi :: NodeId -> GargServer TreeApi
348 treeApi id' = getTree id'
352 getTree :: FlowCmdM env err m
359 -> m (HashedResponse (ChartMetrics [MyTree]))
360 getTree cId _start _end maybeListId tabType listType = do
361 listId <- case maybeListId of
363 Nothing -> defaultList cId
365 node <- getNodeWith listId (Proxy :: Proxy HyperdataList)
366 let HyperdataList { hd_tree = mChart } = node ^. node_hyperdata
368 chart <- case mChart of
369 Just chart -> pure chart
371 updateTree' cId maybeListId tabType listType
373 pure $ constructHashedResponse chart
375 updateTree :: FlowCmdM env err m =>
381 updateTree cId maybeListId tabType listType = do
382 _ <- updateTree' cId maybeListId tabType listType
385 updateTree' :: FlowCmdM env err m =>
390 -> m (ChartMetrics [MyTree])
391 updateTree' cId maybeListId tabType listType = do
392 listId <- case maybeListId of
394 Nothing -> defaultList cId
396 node <- getNodeWith listId (Proxy :: Proxy HyperdataList)
397 let HyperdataList { hd_chart = hdc
400 , hd_pie = hdp } = node ^. node_hyperdata
401 t <- treeData cId (ngramsTypeFromTabType tabType) listType
402 _ <- updateHyperdata listId $ HyperdataList hdc hdl hdp hds (Just $ ChartMetrics t)
404 pure $ ChartMetrics t
406 getTreeMD5 :: FlowCmdM env err m =>
412 getTreeMD5 cId maybeListId tabType listType = do
413 HashedResponse { md5 = md5' } <- getTree cId Nothing Nothing maybeListId tabType listType