123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351(*********************************************************************************)(* Stog *)(* *)(* Copyright (C) 2012-2015 INRIA All rights reserved. *)(* Author: Maxence Guesdon, INRIA Saclay *)(* *)(* This program is free software; you can redistribute it and/or modify *)(* it under the terms of the GNU General Public License as *)(* published by the Free Software Foundation, version 3 of the License. *)(* *)(* This program is distributed in the hope that it will be useful, *)(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *)(* GNU General Public License for more details. *)(* *)(* You should have received a copy of the GNU General Public *)(* License along with this program; if not, write to the Free Software *)(* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA *)(* 02111-1307 USA *)(* *)(* As a special exception, you have permission to link this program *)(* with the OCaml compiler and distribute executables, as long as you *)(* follow the requirements of the GNU GPL in regard to all of the *)(* software in the executable aside from the OCaml compiler. *)(* *)(* Contact: Maxence.Guesdon@inria.fr *)(* *)(*********************************************************************************)(** Computing information from articles. *)openTypes;;openFilter_types;;moduleXR=Xtmpl.RewritemoduleXml=Xtmpl.Xmlletis_archived_docstog=matchTypes.get_defstog.stog_defs("","archived-docs")with|Some(_,[XR.Dcdata])->lettypes=Stog_base.Misc.split_stringcdata.Xml.text[',';';']inlettypes=List.mapStog_base.Misc.strip_stringtypesin(fundoc_id->letdoc=Types.docstogdoc_idinList.memdoc.doc_typetypes)|_->(fun_->true);;letcompute_mapf_wordsf_updatestog=letfdoc_iddocmap=leton_wordmapw=letset=tryTypes.Str_map.findwmapwithNot_found->Types.Doc_set.emptyinletset=Types.Doc_set.adddoc_idsetinTypes.Str_map.addwsetmapinList.fold_lefton_wordmap(f_wordsdoc)inf_updatestog(Tmap.foldfstog.stog_docsTypes.Str_map.empty);;letcompute_topic_mapstog=compute_map(funa->a.doc_topics)(funstogmap->{stogwithstog_docs_by_topic=map})stog;;letcompute_keyword_mapstog=compute_map(funa->a.doc_keywords)(funstogmap->{stogwithstog_docs_by_kw=map})stog;;letcompute_graph_with_datesstog=letis_archived=is_archived_docstoginletpred(doc_id,_)=is_archiveddoc_idinletdocs=Types.doc_list~by_date:truestoginletdocs=List.filterpreddocsinletg=Types.Graph.create()inletreciterg=function[]|[_]->g|(doc_id,_)::(next_id,next)::q->letg=Types.Graph.addg(doc_id,next_id,Types.Date)initerg((next_id,next)::q)in{stogwithstog_graph=itergdocs};;letnext_by_datef_nextstogart_id=letnext=f_nextstog.stog_graphart_idinletnext=List.filter(function(_,Types.Date)->true|_->false)nextinmatchnextwith[]->None|(id,_)::_->Someidletsucc_by_date=next_by_dateTypes.Graph.succ;;letpred_by_date=next_by_dateTypes.Graph.pred;;letadd_words_in_graphstogfedge_data=letget_lasttableword=trySome(Types.Str_map.findwordtable)withNot_found->Noneinletroots=Types.Graph.pred_rootsstog.stog_graphinletadd_for_nodegtableid=letwords=fidinletg=List.fold_left(fungword->matchget_lasttablewordwithNone->g|Someid0->Types.Graph.addg(id0,id,(edge_dataword)))gwordsinlettable=List.fold_left(funtword->Types.Str_map.addwordidt)tablewordsin(g,table)inletrecf(g,table)id=let(g,table)=add_for_nodegtableidinletsuccs=Types.Graph.succgidinletsuccs=List.filter(fun(_,data)->data=Date)succsinletsuccs=Stog_base.Misc.list_remove_doubles(List.mapfstsuccs)inList.fold_leftf(g,table)succsinlet(g,_)=List.fold_leftf(stog.stog_graph,Types.Str_map.empty)rootsin{stogwithstog_graph=g};;letadd_topics_in_graphstog=add_words_in_graphstog(funid->letdoc=Types.docstogidindoc.doc_topics);;letadd_keywords_in_graphstog=add_words_in_graphstog(funid->letdoc=Types.docstogidindoc.doc_keywords);;letadd_refs_in_graphstog=stog(* FIXME: have to compute it differently now
let g = ref stog.stog_graph in
let f_ref id env args body =
match Xtmpl.get_att args ("", "id") with
None ->
[]
| Some path ->
(*prerr_endline (Printf.sprintf "f_ref path=%s" path);*)
(
let (id2, _) = Types.doc_by_path stog
(Path.of_string path)
in
g := Types.Graph.add !g (id, id2, Types.Ref)
);
[]
in
let f_art id art =
let funs = [ "ref", f_ref id ] in
let doc = Types.doc stog id in
let env = Xtmpl.env_of_list funs in
ignore(Xtmpl.apply_to_xmls env doc.doc_body)
in
Tmap.iter f_art stog.stog_docs;
{ stog with stog_graph = !g }
*);;letcompute_archivesstog=letpred=is_archived_docstoginletf_mondoc_idmmmap=letset=tryTypes.Int_map.findmmmapwithNot_found->Types.Doc_set.emptyinletset=Types.Doc_set.adddoc_idsetinletset=Types.Doc_set.filterpredsetinmatchTypes.Doc_set.is_emptysetwithtrue->mmap|false->Types.Int_map.addmsetmmapinletf_artdoc_iddocymap=matchdoc.doc_datewithNone->ymap|Somedt->let((year,month,_),_)=Date.to_date_timedtinletmmap=tryTypes.Int_map.findyearymapwithNot_found->Types.Int_map.emptyinletmmap=f_mondoc_idmonthmmapinTypes.Int_map.addyearmmapymapinletarch=Tmap.foldf_artstog.stog_docsTypes.Int_map.emptyin{stogwithstog_archives=arch};;letcolor_of_texts=letlen=String.lengthsinletr=ref0infori=0tolen-1dor:=!r+Char.codes.[i]done;letg=ref0infori=0tolen-1dog:=!g+(abs(lnot(Char.codes.[i])))done;letb=ref0infori=0tolen-1dob:=!b+((Char.codes.[i])lsl2)done;let(br,bg,bb)=iflen<=2then(true,true,true)else((Char.codes.[0])land5>0,(Char.codes.[1])land5>0,(Char.codes.[2])land5>0)in((ifbrthen20+!rmod180else0),(ifbgthen20+!gmod180else0),(ifbbthen20+!bmod180else0));;letdot_of_graphf_hrefstog=letg=Types.Graph.fold_succstog.stog_graph(funidsuccsg->List.fold_left(fung(id2,edge)->matchedgewithDate->g|d->Types.Graph.addg(id,id2,d))gsuccs)(Types.Graph.create())inletf_edge=functionDate->assertfalse|Topicword|Keywordword->let(r,g,b)=color_of_textwordinletcol=Printf.sprintf"#%02x%02x%02x"rgbin(word,["fontcolor",col;"color",col])|Ref->("",["style","dashed"])inletf_nodeid=letdoc=Types.docstogidinletcol=matchdoc.doc_topicswith[]->"black"|w::_->let(r,g,b)=color_of_textwinPrintf.sprintf"#%02x%02x%02x"rgbinlethref=f_hrefdocin(Printf.sprintf"id%d"(Tmap.intid),doc.doc_title,["shape","rect";"color",col;"fontcolor",col;"href",Url.to_stringhref])inTypes.Graph.dot_of_graph~f_edge~f_nodeg;;letcomputestog=letstog=compute_keyword_mapstoginletstog=compute_topic_mapstoginletstog=compute_graph_with_datesstoginletstog=add_topics_in_graphstog(funw->Types.Topicw)inletstog=add_keywords_in_graphstog(funw->Types.Keywordw)inletstog=add_refs_in_graphstoginletstog=compute_archivesstoginstog;;letrecdoc_verifiesdoc=function|Or(f1,f2)->(doc_verifiesdocf1)||(doc_verifiesdocf2)|And(f1,f2)->(doc_verifiesdocf1)&&(doc_verifiesdocf2)|Notf->not(doc_verifiesdocf)|Pred(("","set"),name)->List.memnamedoc.doc_sets|Pred(("","keyword"),name)->List.memnamedoc.doc_keywords|Pred(("","topic"),name)->List.memnamedoc.doc_topics|Pred(("","type"),v)->doc.doc_type=v|Pred(name,v)->matchTypes.get_defdoc.doc_defsnamewithNone->v=""|Some(_,body)->lets=XR.to_stringbodyinv=s;;letremove_not_publishedstog=letpred=matchstog.stog_publish_onlywithNone->(fun_->true)|Somef->(fundoc->doc_verifiesdocf)inlet(docs,removed)=Tmap.fold(funiddoc(acc,removed)->ifpreddocthen(acc,removed)else(Tmap.removeaccid,doc.doc_path::removed))stog.stog_docs(stog.stog_docs,[])in(*
let by_path = List.fold_left
(fun acc k -> Types.Path_map.remove (List.rev k.path_path) acc)
stog.stog_docs_by_path removed
in
*)letstog=Tmap.fold(fundoc_iddocstog->Types.add_pathstogdoc.doc_pathdoc_id)docs{stogwithstog_docs_by_path=Types.Path_trie.empty}in{stogwithstog_docs=docs;};;