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
22 import qualified Data.Map as Map
23 import Data.Time (UTCTime)
24 import Data.Text (Text)
27 import Gargantext.API.HashedResponse
28 import Gargantext.API.Ngrams
29 import Gargantext.API.Ngrams.NTree
30 import Gargantext.API.Prelude (GargServer)
31 import Gargantext.Core.Types (CorpusId, Limit, ListId, ListType(..))
32 import Gargantext.Database.Action.Flow
33 import Gargantext.Database.Admin.Types.Hyperdata (HyperdataList(..))
34 import Gargantext.Database.Admin.Types.Metrics (ChartMetrics(..), Metric(..), Metrics(..))
35 import Gargantext.Database.Admin.Types.Node (NodeId)
36 import Gargantext.Database.Prelude
37 import Gargantext.Database.Query.Table.Node (defaultList, getNodeWith)
38 import Gargantext.Database.Query.Table.Node.Error (HasNodeError)
39 import Gargantext.Database.Query.Table.Node.UpdateOpaleye (updateHyperdata)
40 import Gargantext.Database.Schema.Node (node_hyperdata)
41 import Gargantext.Prelude
42 import Gargantext.Text.Metrics (Scored(..))
43 import Gargantext.Viz.Chart
44 import Gargantext.Viz.Types
45 import qualified Gargantext.Database.Action.Metrics as Metrics
47 -------------------------------------------------------------
48 -- | Scatter metrics API
49 type ScatterAPI = Summary "SepGen IncExc metrics"
50 :> QueryParam "list" ListId
51 :> QueryParamR "ngramsType" TabType
52 :> QueryParam "limit" Int
53 :> Header "X-Hash" Text
54 :> Get '[JSON] (Headers '[Header "X-Hash" Text] (HashedResponse Metrics))
55 :<|> Summary "Scatter update"
56 :> QueryParam "list" ListId
57 :> QueryParamR "ngramsType" TabType
58 :> QueryParam "limit" Int
61 Summary "Scatter Hash"
62 :> QueryParam "list" ListId
63 :> QueryParamR "ngramsType" TabType
66 scatterApi :: NodeId -> GargServer ScatterAPI
67 scatterApi id' = getScatter id'
68 :<|> updateScatter id'
69 :<|> getScatterHash id'
71 getScatter :: FlowCmdM env err m =>
77 -> m (Headers '[Header "X-Hash" Text] (HashedResponse Metrics))
78 getScatter cId maybeListId tabType _maybeLimit mhHash = do
79 listId <- case maybeListId of
81 Nothing -> defaultList cId
82 node <- getNodeWith listId (Proxy :: Proxy HyperdataList)
83 let HyperdataList { _hl_scatter = mChart } = node ^. node_hyperdata
85 chart <- case mChart of
86 Just chart -> pure chart
88 updateScatter' cId maybeListId tabType Nothing
90 let r = constructHashedResponse chart
92 -- TODO send 304 if hashes equal, 200 with response otherwise
93 if mhHash == (Just $ hash r) then
94 throwError $ ServantErr { errHTTPCode = 304
95 , errReasonPhrase = "Hashes match"
99 pure $ addHeader (hash r) r
101 updateScatter :: FlowCmdM env err m =>
107 updateScatter cId maybeListId tabType maybeLimit = do
108 _ <- updateScatter' cId maybeListId tabType maybeLimit
111 updateScatter' :: FlowCmdM env err m =>
117 updateScatter' cId maybeListId tabType maybeLimit = do
118 (ngs', scores) <- Metrics.getMetrics cId maybeListId tabType maybeLimit
121 metrics = map (\(Scored t s1 s2) -> Metric t (log' 5 s1) (log' 2 s2) (listType t ngs')) scores
122 log' n x = 1 + (if x <= 0 then 0 else log $ (10^(n::Int)) * x)
123 listType t m = maybe (panic errorMsg) fst $ Map.lookup t m
124 errorMsg = "API.Node.metrics: key absent"
126 listId <- case maybeListId of
128 Nothing -> defaultList cId
129 node <- getNodeWith listId (Proxy :: Proxy HyperdataList)
130 let hl = node ^. node_hyperdata
131 _ <- updateHyperdata listId $ hl { _hl_scatter = Just $ Metrics metrics }
133 pure $ Metrics metrics
135 getScatterHash :: FlowCmdM env err m =>
140 getScatterHash cId maybeListId tabType = do
141 r <- getScatter cId maybeListId tabType Nothing Nothing
142 pure $ hash $ getResponse r
145 -------------------------------------------------------------
146 -- | Chart metrics API
147 type ChartApi = Summary " Chart API"
148 :> QueryParam "from" UTCTime
149 :> QueryParam "to" UTCTime
150 :> QueryParam "list" ListId
151 :> QueryParamR "ngramsType" TabType
152 :> Get '[JSON] (HashedResponse (ChartMetrics Histo))
153 :<|> Summary "Chart update"
154 :> QueryParam "list" ListId
155 :> QueryParamR "ngramsType" TabType
156 :> QueryParam "limit" Int
160 :> QueryParam "list" ListId
161 :> QueryParamR "ngramsType" TabType
164 chartApi :: NodeId -> GargServer ChartApi
165 chartApi id' = getChart id'
167 :<|> getChartHash id'
169 -- TODO add start / end
170 getChart :: FlowCmdM env err m =>
176 -> m (HashedResponse (ChartMetrics Histo))
177 getChart cId _start _end maybeListId tabType = do
178 listId <- case maybeListId of
180 Nothing -> defaultList cId
181 node <- getNodeWith listId (Proxy :: Proxy HyperdataList)
182 let HyperdataList { _hl_chart = mChart } = node ^. node_hyperdata
184 chart <- case mChart of
185 Just chart -> pure chart
187 updateChart' cId maybeListId tabType Nothing
189 pure $ constructHashedResponse chart
191 updateChart :: HasNodeError err =>
197 updateChart cId maybeListId tabType maybeLimit = do
198 _ <- updateChart' cId maybeListId tabType maybeLimit
201 updateChart' :: HasNodeError err =>
206 -> Cmd err (ChartMetrics Histo)
207 updateChart' cId maybeListId _tabType _maybeLimit = do
208 listId <- case maybeListId of
210 Nothing -> defaultList cId
211 node <- getNodeWith listId (Proxy :: Proxy HyperdataList)
212 let hl = node ^. node_hyperdata
214 _ <- updateHyperdata listId $ hl { _hl_chart = Just $ ChartMetrics h }
216 pure $ ChartMetrics h
219 getChartHash :: FlowCmdM env err m =>
224 getChartHash cId maybeListId tabType = do
225 hash <$> getChart cId Nothing Nothing maybeListId tabType
227 -------------------------------------------------------------
229 type PieApi = Summary "Pie Chart"
230 :> QueryParam "from" UTCTime
231 :> QueryParam "to" UTCTime
232 :> QueryParam "list" ListId
233 :> QueryParamR "ngramsType" TabType
234 :> Get '[JSON] (HashedResponse (ChartMetrics Histo))
235 :<|> Summary "Pie Chart update"
236 :> QueryParam "list" ListId
237 :> QueryParamR "ngramsType" TabType
238 :> QueryParam "limit" Int
242 :> QueryParam "list" ListId
243 :> QueryParamR "ngramsType" TabType
246 pieApi :: NodeId -> GargServer PieApi
247 pieApi id' = getPie id'
251 getPie :: FlowCmdM env err m
257 -> m (HashedResponse (ChartMetrics Histo))
258 getPie cId _start _end maybeListId tabType = do
259 listId <- case maybeListId of
261 Nothing -> defaultList cId
262 node <- getNodeWith listId (Proxy :: Proxy HyperdataList)
263 let HyperdataList { _hl_pie = mChart } = node ^. node_hyperdata
265 chart <- case mChart of
266 Just chart -> pure chart
268 updatePie' cId maybeListId tabType Nothing
270 pure $ constructHashedResponse chart
272 updatePie :: FlowCmdM env err m =>
278 updatePie cId maybeListId tabType maybeLimit = do
279 _ <- updatePie' cId maybeListId tabType maybeLimit
282 updatePie' :: FlowCmdM env err m =>
287 -> m (ChartMetrics Histo)
288 updatePie' cId maybeListId tabType _maybeLimit = do
289 listId <- case maybeListId of
291 Nothing -> defaultList cId
292 node <- getNodeWith listId (Proxy :: Proxy HyperdataList)
293 let hl = node ^. node_hyperdata
295 p <- pieData cId (ngramsTypeFromTabType tabType) MapTerm
296 _ <- updateHyperdata listId $ hl { _hl_pie = Just $ ChartMetrics p }
298 pure $ ChartMetrics p
300 getPieHash :: FlowCmdM env err m =>
305 getPieHash cId maybeListId tabType = do
306 hash <$> getPie cId Nothing Nothing maybeListId tabType
308 -------------------------------------------------------------
309 -- | Tree metrics API
311 type TreeApi = Summary " Tree API"
312 :> QueryParam "from" UTCTime
313 :> QueryParam "to" UTCTime
314 :> QueryParam "list" ListId
315 :> QueryParamR "ngramsType" TabType
316 :> QueryParamR "listType" ListType
317 :> Get '[JSON] (HashedResponse (ChartMetrics [MyTree]))
318 :<|> Summary "Tree Chart update"
319 :> QueryParam "list" ListId
320 :> QueryParamR "ngramsType" TabType
321 :> QueryParamR "listType" ListType
325 :> QueryParam "list" ListId
326 :> QueryParamR "ngramsType" TabType
327 :> QueryParamR "listType" ListType
330 -- Depending on the Type of the Node, we could post
331 -- New documents for a corpus
332 -- New map list terms
333 -- :<|> "process" :> MultipartForm MultipartData :> Post '[JSON] Text
335 treeApi :: NodeId -> GargServer TreeApi
336 treeApi id' = getTree id'
340 getTree :: FlowCmdM env err m
347 -> m (HashedResponse (ChartMetrics [MyTree]))
348 getTree cId _start _end maybeListId tabType listType = do
349 listId <- case maybeListId of
351 Nothing -> defaultList cId
353 node <- getNodeWith listId (Proxy :: Proxy HyperdataList)
354 let HyperdataList { _hl_tree = mChart } = node ^. node_hyperdata
356 chart <- case mChart of
357 Just chart -> pure chart
359 updateTree' cId maybeListId tabType listType
361 pure $ constructHashedResponse chart
363 updateTree :: FlowCmdM env err m =>
369 updateTree cId maybeListId tabType listType = do
370 _ <- updateTree' cId maybeListId tabType listType
373 updateTree' :: FlowCmdM env err m =>
378 -> m (ChartMetrics [MyTree])
379 updateTree' cId maybeListId tabType listType = do
380 listId <- case maybeListId of
382 Nothing -> defaultList cId
384 node <- getNodeWith listId (Proxy :: Proxy HyperdataList)
385 let hl = node ^. node_hyperdata
386 t <- treeData cId (ngramsTypeFromTabType tabType) listType
387 _ <- updateHyperdata listId $ hl { _hl_tree = Just $ ChartMetrics t }
389 pure $ ChartMetrics t
391 getTreeHash :: FlowCmdM env err m =>
397 getTreeHash cId maybeListId tabType listType = do
398 hash <$> getTree cId Nothing Nothing maybeListId tabType listType