diff options
author | Martin Czygan <martin.czygan@gmail.com> | 2021-04-21 17:49:12 +0200 |
---|---|---|
committer | Martin Czygan <martin.czygan@gmail.com> | 2021-04-21 17:49:12 +0200 |
commit | 3cb5513cb405af78a01750a29a93be28ac5d90e4 (patch) | |
tree | 46774566984606a113a17803da81f3b14ada742f | |
parent | ae9e380225be648ced23d814cd1d08d1621976bd (diff) | |
download | refcat-3cb5513cb405af78a01750a29a93be28ac5d90e4.tar.gz refcat-3cb5513cb405af78a01750a29a93be28ac5d90e4.zip |
wip: a few dot examples
-rw-r--r-- | extra/dot/example_inbound.dot | 195 | ||||
-rw-r--r-- | extra/dot/example_inbound.png | bin | 0 -> 699674 bytes | |||
-rw-r--r-- | extra/dot/levels_inbound.py | 73 | ||||
-rw-r--r-- | skate/.gitignore | 2 | ||||
-rw-r--r-- | skate/Makefile | 2 | ||||
-rw-r--r-- | skate/cmd/skate-dot/main.go | 80 | ||||
-rw-r--r-- | skate/go.mod | 2 | ||||
-rw-r--r-- | skate/go.sum | 4 | ||||
-rw-r--r-- | skate/wordwrap/wordwrap.go | 83 | ||||
-rw-r--r-- | skate/wordwrap/wordwrap_test.go | 99 |
10 files changed, 538 insertions, 2 deletions
diff --git a/extra/dot/example_inbound.dot b/extra/dot/example_inbound.dot new file mode 100644 index 0000000..9beb263 --- /dev/null +++ b/extra/dot/example_inbound.dot @@ -0,0 +1,195 @@ +digraph G { + node [ style="solid" shape="box" fontname="Arial" fontsize="12" fontcolor="black" ]; + "fzxizmxeybazhoswj5kvxl7fky" [label="Relating Data\nRefinement\nand Failures-Divergences\nRefinement\n(2018)"]; + "idt3qiwgffh2rid46v4vh7qh4m" [label="Generality\nin design and\ncompositional\nverification\nusingTav (1995)"]; + "5hxst5pboja3dntwcx5xmfb6vu" [label="Proving Opacity\nvia Linearizability:\nA Sound and\nComplete Method\n(2017)"]; + "ki6z42ugjreqzmdfc7hv72ddny" [label="CPL: a core\nlanguage for\ncloud computing\n(2016)"]; + "vztpo3kn6rgbvgvnyvkpa7r2cu" [label="Reward Testing\nEquivalences\nfor Processes\n(2019)"]; + "dtdp4dlhmvf2fbw2rsmfdhg7jq" [label="Checking Consistency\nin UML Diagrams:\nClasses and\nState Machines\n(2003)"]; + "iodn5pvvk5fg3d63nwbs3iqp3i" [label="BSP-Why: A\nTool for Deductive\nVerification\nof BSP Algorithms\nwith Subgroup\nSynchronisation\n(2015)"]; + "z53wdeubi5egnns7h55wv2vpt4" [label="A proof technique\nfor communicating\nsequential\nprocesses (1981)"]; + "uddghbfzbbfrtdc6sqirck7pqm" [label="Unified Modelling\nFunctional\nand Non-Functional\nAspects of\nWeb Services\nComposition\nUsing PTCCS\n(2011)"]; + "kmhwb6yju5gwvoqlirfpzpipka" [label="A FRAMEWORK\nFOR THE EVALUATION\nOF REAL-TIME\nSPECIFICATION\nTECHNIQUES\n(2006)"]; + "2rqolf6o6jgsdkishicri2wirm" [label="An improved\nfailures model\nfor communicating\nprocesses (1985)"]; + "lb6746dmrbg75gnbcrv3qavere" [label="TESTOR: A Modular\nTool for On-the-Fly\nConformance\nTest Case Generation\n(2018)"]; + "ixrau56runetxbqy7olqvods2y" [label="Graphics Related\nActivities\nat NCSDCT,\nBombay (1983)"]; + "hdwrpnaabzeqvoh6yugn3ti6lm" [label="Vulnerability\nAnalysis of\nCSP Based on\nStochastic\nGame Theory\n(2016)"]; + "cpq5tedh2jb7zbekcqgdpeigyi" [label="More Automated\nFormal Methods?!\nIf so, why,\nwhere & how?"]; + "26axhnld75dp3k6ruj7qm6lvbi" [label="Asynchronous\nTesting of\nSynchronous\nComponents\nin GALS Systems\n(2019)"]; + "erfn3kiztvcvhj2ksskgrzttyy" [label="Calculating\nParallel Programs\nin Coq Using\nList Homomorphisms\n(2016)"]; + "wwxzdcpcvrcefmw7o25wvwgjau" [label="AXIOMATIC FRAMEWORKS\nFOR DEVELOPING\nBSP-STYLE PROGRAMS∗\n(2000)"]; + "w6nyuz43fffktacvoq2vnkqwdq" [label="Encoding CSP\ninto CCS (2015)"]; + "xmc5nch3wfgvjdgfhlu3gfr7ga" [label="Resource-Aware\nVirtually Timed\nAmbients (2018)"]; + "nazgn3i735e5fabigbyugjm6lu" [label="Correct and\nEfficient Antichain\nAlgorithms\nfor Refinement\nChecking (2019)"]; + "n2j6o5sjnnc3pgtw23f7pg4uym" [label="Refinement\nand Consistency\nin Component\nModels with\nMultiple Views\n(2006)"]; + "nqniiaq2cjezfjxs5ezlqfajl4" [label="Taming Concurrency\nfor Verification\nUsing Multiparty\nSession Types\n(2019)"]; + "atgnqdcm65b33c5uf77el6fvni" [label="A Correctness\nChecking Approach\nfor Collaborative\nBusiness Processes\nin the Cloud\n(2020)"]; + "mxk2kan4kngqtj5s7zbmpokpua" [label="A Relational\nView of Refinement\n(2018)"]; + "jqptucpeebfetm77ov32zjtjhy" [label="Reflections\non Bernhard\nSteffen's Physics\nof Software\nTools (2019)"]; + "hhtadeldyfeudh7zv7li4zarbm" [label="Stronger Validity\nCriteria for\nEncoding Synchrony\n(2019)"]; + "7w6cjfy7ljfx7i3v2z3hazii3a" [label="Reversibility\nin session-based\nconcurrency:\nA fresh look\n(2017)"]; + "xup26exlhjbtjnlzs3ya6r5opi" [label="30 Years of\nModal Transition\nSystems: Survey\nof Extensions\nand Analysis\n(2017)"]; + "2mhbxewq3rczdjjtbpqsl4if4q" [label="Characteristic\nbisimulation\nfor higher-order\nsession processes\n(2016)"]; + "jq2l5dpeknbqlnyt5gbozszkzy" [label="Communicating\nsequential\nprocesses (1978)" style="filled" fillcolor="orange"]; + "pgcis54ngfa53o5hawkdeqfria" [label="Hybrid CSP\n(2016)"]; + "xysudaucabb3flreoy2iztxj6a" [label="FastLane Is\nOpaque – a\nCase Study\nin Mechanized\nProofs of Opacity\n(2018)"]; + "tyjh5qifcje47pczionoa2dz6y" [label="A state-based\napproach to\ncommunicating\nprocesses (1988)"]; + "ij7mnzknkjbbxkhy3k2cscxfqy" [label="Coupled similarity:\nthe first 32\nyears (2019)"]; + "zy2tq4erqrfrborv5d24opidly" [label="Defining and\nVerifying Durable\nOpacity: Correctness\nfor Persistent\nSoftware Transactional\nMemory (2020)"]; + "cyv5n3dl55hehpef2pizxuqwm4" [label="Validating\nHigh-Level\nSynthesis"]; + "rbbqg7nhsfdfnaphwfuwqmujvy" [label="Deriving failures\nmodels for\nnonuniform\nconcurrency\nfrom structured\noperational\nsemantics (1996)"]; + "ipohy4pmfjakfosou7hruin7x4" [label="JDAS: a software\ndevelopment\nframework for\nmultidatabases\n(2017)"]; + "dm2kmtw5t5aldcbjgwbc6o3pmi" [label="Failure Trace\nSemantics for\na Process Algebra\nwith Time-outs\n(preliminary\nreport) (2020)"]; + "yctmdvbdxrgglagwiehlhvac3e" [label="Relational\nConcurrent\nRefinement\n(2018)"]; + "vrcagvkzrzdxnbslhvaignf6si" [label="Component-aware\nInput-Output\nConformance\n(2019)"]; + "ee4enzkzhvbrha46bzlmerxcsq" [label="Parameterizing\nhigher-order\nprocesses on\nnames and processes\n(2020)"]; + "7xtcdmozsjh6lppwflvell7qnm" [label="SDN Protocol\nAnalysis with\nProcess Algebra\nMethod (2017)"]; + "xa33ovyyy5aolab4iuj5oneokq" [label="Specification-oriented\nsemantics for\nCommunicating\nProcesses (1986)"]; + "yoyygplnt5bxphait6dzdlg534" [label="Checking Modal\nContracts for\nVirtually Timed\nAmbients (2018)"]; + "gpw35r4invcfln46vulj65f7xm" [label="Modelling Divergence\nin Relational\nConcurrent\nRefinement\n(2009)"]; + "pdegi4sig5fp5mavy4hqmcugre" [label="On the Expressiveness\nof Symmetric\nCommunication\n(2016)"]; + "hjtusiibtbho7cxqf56zuuqtg4" [label="A Note on the\nExpressiveness\nof BIP (2016)"]; + "42c3kolvbvhtdjznoqarjl4574" [label="A Branching\nTime Model\nof CSP (2016)"]; + "hidk5ja4rfbddp6tgaodiqxcmi" [label="Adopting Formal\nMethods in\nan Industrial\nSetting: The\nRailways Case\n(2019)"]; + "l2cvg6kg7jabtbtno6gecug6ky" [label="A Branching\nTime Model\nof CSP (2017)"]; + "mjzpcsji65f2rlmlujanu3nila" [label="Hiding in stream\nsemantics of\nuniform concurrency\n(1990)"]; + "mfz7bqc5pjgnrojlmsfepz37qe" [label="Musings on\nEncodings and\nExpressiveness\n(2012)"]; + "2bbo7hkoe5cbblknsd3nwczapa" [label="Expressiveness\nof component-based\nframeworks:\na study of\nthe expressiveness\nof BIP (2019)"]; + "l6qrrsnysrf2hfmyop4bqhtwma" [label="A Theory of\nEncodings and\nExpressiveness\n(Extended Abstract)\n(2018)"]; + "e7p4e4juw5fs3fqxyfvwfkc2mq" [label="Step failures\nsemantics and\na complete\nproof system\n(1989)"]; + "luxpiyqihjbdzevahl6i5lgfi4" [label="Towards safe\nmodular composition\nof network\nfunctions (2018)"]; + "wf7hn3gqqfdx3epkvh3hzczisy" [label="Evidential\nand Continuous\nIntegration\nof Software\nVerification\nTools (2018)"]; + "rcm72e4pyvgvnkaixi4t7kypvy" [label="Causally consistent\nreversible\nchoreographies\n(2017)"]; + "u2tggttxbbbzfdyggh24vuusti" [label="An Approach\nBased on Hierarchical\nPetri Nets\nfor the Verification\nof Interconnected\nBPEL Processes\n(2018)"]; + "mn2j7unnnfclfdc2w5ajnqxram" [label="Multi-ML: Programming\nMulti-BSP Algorithms\nin ML (2016)"]; + "y6mx3k2dejdephkuwksc64n2ai" [label="The Challenge\nof Typed Expressiveness\nin Concurrency\n(2016)"]; + "sydba4xpuff7hdkegjftx3ff5e" [label="Comparing Process\nCalculi Using\nEncodings (2019)"]; + "k6h2vy5q2nf4tmzgkf2trkppf4" [label="A Calculus\nof Virtually\nTimed Ambients\n(2017)"]; + "nprtqlxnhrbq3esjlysvismvhy" [label="Transaction\nProtocol Verification\nwith Labeled\nSynchronization\nLogic (2019)"]; + "b6zqaz2xzvc55bao72xwawsg5u" [label="On Modal Refinement\nand Consistency"]; + "6px4hrvt65h43n7enhvidbolza" [label="External and\ninternal choice\nwith event\ngroups in Event-B\n(2012)"]; + "d3qimowb2vdaphditthyex3d3m" [label="Combining Model\nRefinement\nand Test Generation\nfor Conformance\nTesting of\nthe IEEE PHD\nProtocol Using\nAbstract State\nMachines (2019)"]; + "24n7gsewsngrdkolvalzrs2nhe" [label="Modeling and\nverification\nof Web services\ncomposition\nbased on model\ntransformation\n(2016)"]; + "qtqir242zva73h363kajbkvsyi" [label="Analysing and\nComparing Encodability\nCriteria (2015)"]; + "jcx6brqljbcebkizk4cdjeatyu" [label="On the Relative\nExpressiveness\nof Higher-Order\nSession Processes\n(2016)"]; + "v5htlznfpnex7d2js5zwy47eeu" [label="A Logical Interface\nDescription\nLanguage for\nComponents\n(2000)"]; + "dpjpdyjd35dmbg774v2kgqb3ge" [label="Formal modeling\nand verification\nof cloud‐based\nweb service\ncomposition\n(2019)"]; + "x7s3reyu25bixgdgx4y3kwf2ci" [label="Modelling and\nanalysing neural\nnetworks using\na hybrid process\nalgebra (2016)"]; + "4677h7puyjc2picqlgwdelmybi" [label="On the Expressiveness\nof Joining\n(2015)"]; + "f6d5clvuifgxhg7fpwrngctccq" [label="Strategy Synthesis\nfor Autonomous\nDriving in\na Moving Block\nRailway System\nwith Uppaal\nStratego (2020)"]; + "bumvudnas5cqtjs3in7pb4bnua" [label="Computing Coupled\nSimilarity\n(2019)"]; + "lpqosqmr6bhcbazkvnbythddwy" [label="On Characterising\nDistributability\n(2013)"]; + "vsmvxmfujndmfbuoz27ygabzf4" [label="Total correctness\nof CSP programs\n(1986)"]; + "5ouybxooxvf55ibckfuyflm55y" [label="Turing und\ndie Verifikation\n(2012)"]; + "vzxfucuz45fozhicmxzkxdpdjm" [label="Fifty years\nof Hoare's\nlogic (2019)"]; + "ir4f556pvvddpbchro7vhffjtq" [label="Applications\nof compactness\nin the Smyth\npowerdomain\nof streams\n(1987)"]; + "yjywveqbw5g3nhzqrx7ryvmjty" [label="Inductive Proof\nOutlines for\nMonitors in\nJava (2003)"]; + "tvxk2b6z2jamzn6rsnkq6mjwb4" [label="Simulating\nTruly Concurrent\nCSP (2011)"]; + "nfgui7zbfbe3tdbso2zmffbwpy" [label="Higher-order\nProcesses with\nParameterization\nover Names\nand Processes\n(2016)"]; + "hwu7b64kh5brrlm7spzyucxibe" [label="Some recent\nadvances in\nautomated analysis\n(2015)"]; + "x5amfr7c2zes3cspw32m5my4de" [label="Reversible\nSession-Based\nConcurrency\nin Haskell\n(2019)"]; + "wxqp6cbl3rbz5jycbasfnski5u" [label="Alan Turing\n– Aus Leben\nund Werk eines\naußergewöhnlichen\nMenschen (2013)"]; + "ca7g736vorcobkam2244hj2yry" [label="On the Meaning\nof Transition\nSystem Specifications\n(2019)"]; + "lb4gnwjzqra4tc6on6tz5qsgjy" [label="SAMENVATTING\nIN HET NEDERLANDS"]; + "lpqosqmr6bhcbazkvnbythddwy" -> "e7p4e4juw5fs3fqxyfvwfkc2mq"; + "vzxfucuz45fozhicmxzkxdpdjm" -> "5ouybxooxvf55ibckfuyflm55y"; + "mfz7bqc5pjgnrojlmsfepz37qe" -> "xa33ovyyy5aolab4iuj5oneokq"; + "pgcis54ngfa53o5hawkdeqfria" -> "xa33ovyyy5aolab4iuj5oneokq"; + "fzxizmxeybazhoswj5kvxl7fky" -> "tyjh5qifcje47pczionoa2dz6y"; + "l2cvg6kg7jabtbtno6gecug6ky" -> "xa33ovyyy5aolab4iuj5oneokq"; + "atgnqdcm65b33c5uf77el6fvni" -> "24n7gsewsngrdkolvalzrs2nhe"; + "x7s3reyu25bixgdgx4y3kwf2ci" -> "2rqolf6o6jgsdkishicri2wirm"; + "cyv5n3dl55hehpef2pizxuqwm4" -> "tyjh5qifcje47pczionoa2dz6y"; + "b6zqaz2xzvc55bao72xwawsg5u" -> "idt3qiwgffh2rid46v4vh7qh4m"; + "vrcagvkzrzdxnbslhvaignf6si" -> "lb6746dmrbg75gnbcrv3qavere"; + "zy2tq4erqrfrborv5d24opidly" -> "5hxst5pboja3dntwcx5xmfb6vu"; + "wxqp6cbl3rbz5jycbasfnski5u" -> "5ouybxooxvf55ibckfuyflm55y"; + "x5amfr7c2zes3cspw32m5my4de" -> "jcx6brqljbcebkizk4cdjeatyu"; + "uddghbfzbbfrtdc6sqirck7pqm" -> "jq2l5dpeknbqlnyt5gbozszkzy"; + "jcx6brqljbcebkizk4cdjeatyu" -> "qtqir242zva73h363kajbkvsyi"; + "iodn5pvvk5fg3d63nwbs3iqp3i" -> "wwxzdcpcvrcefmw7o25wvwgjau"; + "42c3kolvbvhtdjznoqarjl4574" -> "2rqolf6o6jgsdkishicri2wirm"; + "2bbo7hkoe5cbblknsd3nwczapa" -> "mfz7bqc5pjgnrojlmsfepz37qe"; + "d3qimowb2vdaphditthyex3d3m" -> "lb6746dmrbg75gnbcrv3qavere"; + "rcm72e4pyvgvnkaixi4t7kypvy" -> "jcx6brqljbcebkizk4cdjeatyu"; + "luxpiyqihjbdzevahl6i5lgfi4" -> "ki6z42ugjreqzmdfc7hv72ddny"; + "hhtadeldyfeudh7zv7li4zarbm" -> "qtqir242zva73h363kajbkvsyi"; + "k6h2vy5q2nf4tmzgkf2trkppf4" -> "ki6z42ugjreqzmdfc7hv72ddny"; + "hwu7b64kh5brrlm7spzyucxibe" -> "z53wdeubi5egnns7h55wv2vpt4"; + "mxk2kan4kngqtj5s7zbmpokpua" -> "tyjh5qifcje47pczionoa2dz6y"; + "wwxzdcpcvrcefmw7o25wvwgjau" -> "z53wdeubi5egnns7h55wv2vpt4"; + "v5htlznfpnex7d2js5zwy47eeu" -> "xa33ovyyy5aolab4iuj5oneokq"; + "nprtqlxnhrbq3esjlysvismvhy" -> "5hxst5pboja3dntwcx5xmfb6vu"; + "pdegi4sig5fp5mavy4hqmcugre" -> "mfz7bqc5pjgnrojlmsfepz37qe"; + "nazgn3i735e5fabigbyugjm6lu" -> "42c3kolvbvhtdjznoqarjl4574"; + "e7p4e4juw5fs3fqxyfvwfkc2mq" -> "xa33ovyyy5aolab4iuj5oneokq"; + "ipohy4pmfjakfosou7hruin7x4" -> "24n7gsewsngrdkolvalzrs2nhe"; + "yjywveqbw5g3nhzqrx7ryvmjty" -> "z53wdeubi5egnns7h55wv2vpt4"; + "ij7mnzknkjbbxkhy3k2cscxfqy" -> "qtqir242zva73h363kajbkvsyi"; + "vzxfucuz45fozhicmxzkxdpdjm" -> "z53wdeubi5egnns7h55wv2vpt4"; + "24n7gsewsngrdkolvalzrs2nhe" -> "uddghbfzbbfrtdc6sqirck7pqm"; + "bumvudnas5cqtjs3in7pb4bnua" -> "42c3kolvbvhtdjznoqarjl4574"; + "xmc5nch3wfgvjdgfhlu3gfr7ga" -> "k6h2vy5q2nf4tmzgkf2trkppf4"; + "z53wdeubi5egnns7h55wv2vpt4" -> "jq2l5dpeknbqlnyt5gbozszkzy"; + "y6mx3k2dejdephkuwksc64n2ai" -> "jcx6brqljbcebkizk4cdjeatyu"; + "yctmdvbdxrgglagwiehlhvac3e" -> "tyjh5qifcje47pczionoa2dz6y"; + "hhtadeldyfeudh7zv7li4zarbm" -> "l6qrrsnysrf2hfmyop4bqhtwma"; + "42c3kolvbvhtdjznoqarjl4574" -> "xa33ovyyy5aolab4iuj5oneokq"; + "sydba4xpuff7hdkegjftx3ff5e" -> "mfz7bqc5pjgnrojlmsfepz37qe"; + "mjzpcsji65f2rlmlujanu3nila" -> "xa33ovyyy5aolab4iuj5oneokq"; + "ixrau56runetxbqy7olqvods2y" -> "jq2l5dpeknbqlnyt5gbozszkzy"; + "hjtusiibtbho7cxqf56zuuqtg4" -> "mfz7bqc5pjgnrojlmsfepz37qe"; + "lb4gnwjzqra4tc6on6tz5qsgjy" -> "e7p4e4juw5fs3fqxyfvwfkc2mq"; + "qtqir242zva73h363kajbkvsyi" -> "mfz7bqc5pjgnrojlmsfepz37qe"; + "lb6746dmrbg75gnbcrv3qavere" -> "jq2l5dpeknbqlnyt5gbozszkzy"; + "2rqolf6o6jgsdkishicri2wirm" -> "z53wdeubi5egnns7h55wv2vpt4"; + "hdwrpnaabzeqvoh6yugn3ti6lm" -> "jq2l5dpeknbqlnyt5gbozszkzy"; + "cpq5tedh2jb7zbekcqgdpeigyi" -> "hwu7b64kh5brrlm7spzyucxibe"; + "mn2j7unnnfclfdc2w5ajnqxram" -> "iodn5pvvk5fg3d63nwbs3iqp3i"; + "f6d5clvuifgxhg7fpwrngctccq" -> "hidk5ja4rfbddp6tgaodiqxcmi"; + "gpw35r4invcfln46vulj65f7xm" -> "tyjh5qifcje47pczionoa2dz6y"; + "tvxk2b6z2jamzn6rsnkq6mjwb4" -> "e7p4e4juw5fs3fqxyfvwfkc2mq"; + "jqptucpeebfetm77ov32zjtjhy" -> "lb6746dmrbg75gnbcrv3qavere"; + "dtdp4dlhmvf2fbw2rsmfdhg7jq" -> "tyjh5qifcje47pczionoa2dz6y"; + "5hxst5pboja3dntwcx5xmfb6vu" -> "jq2l5dpeknbqlnyt5gbozszkzy"; + "mfz7bqc5pjgnrojlmsfepz37qe" -> "2rqolf6o6jgsdkishicri2wirm"; + "6px4hrvt65h43n7enhvidbolza" -> "tyjh5qifcje47pczionoa2dz6y"; + "wf7hn3gqqfdx3epkvh3hzczisy" -> "hwu7b64kh5brrlm7spzyucxibe"; + "dm2kmtw5t5aldcbjgwbc6o3pmi" -> "l6qrrsnysrf2hfmyop4bqhtwma"; + "yoyygplnt5bxphait6dzdlg534" -> "k6h2vy5q2nf4tmzgkf2trkppf4"; + "tyjh5qifcje47pczionoa2dz6y" -> "2rqolf6o6jgsdkishicri2wirm"; + "ir4f556pvvddpbchro7vhffjtq" -> "mjzpcsji65f2rlmlujanu3nila"; + "hidk5ja4rfbddp6tgaodiqxcmi" -> "jqptucpeebfetm77ov32zjtjhy"; + "vsmvxmfujndmfbuoz27ygabzf4" -> "z53wdeubi5egnns7h55wv2vpt4"; + "kmhwb6yju5gwvoqlirfpzpipka" -> "jq2l5dpeknbqlnyt5gbozszkzy"; + "n2j6o5sjnnc3pgtw23f7pg4uym" -> "tyjh5qifcje47pczionoa2dz6y"; + "4677h7puyjc2picqlgwdelmybi" -> "mfz7bqc5pjgnrojlmsfepz37qe"; + "jcx6brqljbcebkizk4cdjeatyu" -> "mfz7bqc5pjgnrojlmsfepz37qe"; + "dpjpdyjd35dmbg774v2kgqb3ge" -> "24n7gsewsngrdkolvalzrs2nhe"; + "w6nyuz43fffktacvoq2vnkqwdq" -> "qtqir242zva73h363kajbkvsyi"; + "ij7mnzknkjbbxkhy3k2cscxfqy" -> "42c3kolvbvhtdjznoqarjl4574"; + "nqniiaq2cjezfjxs5ezlqfajl4" -> "qtqir242zva73h363kajbkvsyi"; + "hhtadeldyfeudh7zv7li4zarbm" -> "mfz7bqc5pjgnrojlmsfepz37qe"; + "7w6cjfy7ljfx7i3v2z3hazii3a" -> "jcx6brqljbcebkizk4cdjeatyu"; + "ee4enzkzhvbrha46bzlmerxcsq" -> "jcx6brqljbcebkizk4cdjeatyu"; + "ca7g736vorcobkam2244hj2yry" -> "l6qrrsnysrf2hfmyop4bqhtwma"; + "bumvudnas5cqtjs3in7pb4bnua" -> "qtqir242zva73h363kajbkvsyi"; + "xup26exlhjbtjnlzs3ya6r5opi" -> "idt3qiwgffh2rid46v4vh7qh4m"; + "sydba4xpuff7hdkegjftx3ff5e" -> "qtqir242zva73h363kajbkvsyi"; + "rbbqg7nhsfdfnaphwfuwqmujvy" -> "2rqolf6o6jgsdkishicri2wirm"; + "5ouybxooxvf55ibckfuyflm55y" -> "z53wdeubi5egnns7h55wv2vpt4"; + "26axhnld75dp3k6ruj7qm6lvbi" -> "lb6746dmrbg75gnbcrv3qavere"; + "nazgn3i735e5fabigbyugjm6lu" -> "2rqolf6o6jgsdkishicri2wirm"; + "ki6z42ugjreqzmdfc7hv72ddny" -> "jq2l5dpeknbqlnyt5gbozszkzy"; + "xysudaucabb3flreoy2iztxj6a" -> "5hxst5pboja3dntwcx5xmfb6vu"; + "l6qrrsnysrf2hfmyop4bqhtwma" -> "qtqir242zva73h363kajbkvsyi"; + "nfgui7zbfbe3tdbso2zmffbwpy" -> "jcx6brqljbcebkizk4cdjeatyu"; + "2mhbxewq3rczdjjtbpqsl4if4q" -> "jcx6brqljbcebkizk4cdjeatyu"; + "erfn3kiztvcvhj2ksskgrzttyy" -> "iodn5pvvk5fg3d63nwbs3iqp3i"; + "xa33ovyyy5aolab4iuj5oneokq" -> "2rqolf6o6jgsdkishicri2wirm"; + "7xtcdmozsjh6lppwflvell7qnm" -> "x7s3reyu25bixgdgx4y3kwf2ci"; + "vztpo3kn6rgbvgvnyvkpa7r2cu" -> "xa33ovyyy5aolab4iuj5oneokq"; + "u2tggttxbbbzfdyggh24vuusti" -> "24n7gsewsngrdkolvalzrs2nhe"; + "sydba4xpuff7hdkegjftx3ff5e" -> "l6qrrsnysrf2hfmyop4bqhtwma"; + "idt3qiwgffh2rid46v4vh7qh4m" -> "2rqolf6o6jgsdkishicri2wirm"; +} diff --git a/extra/dot/example_inbound.png b/extra/dot/example_inbound.png Binary files differnew file mode 100644 index 0000000..98a848d --- /dev/null +++ b/extra/dot/example_inbound.png diff --git a/extra/dot/levels_inbound.py b/extra/dot/levels_inbound.py new file mode 100644 index 0000000..290ab6f --- /dev/null +++ b/extra/dot/levels_inbound.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python + +""" +Take a document fatcat id and emit the citation structure up to X levels as graphviz dot file. +""" + +from elasticsearch import Elasticsearch +from elasticsearch_dsl import Search +import sys +import requests + +seed = sys.argv[1] if len(sys.argv) > 1 else "rgzyfbx7t5d53m5amvbllewzqi" +max_nodes = 50 + +client = Elasticsearch("http://localhost:9200") +S = Search(using=client, index="fatcat_ref_v01") + +def pretty_label(s, k=10): + parts = s.split() + cur, result =[], [] + for p in parts: + if len(" ".join(cur)) < k: + cur.append(p) + else: + result.append(" ".join(cur)) + cur = [] + result.append(" ".join(cur)) + return "\\n".join(result) + +def get_dot_label(ident): + title = requests.get("https://api.fatcat.wiki/v0/release/{}".format(ident)).json().get("title") + return pretty_label(title, k=10) + + +def unique_sources(ident): + """ + Unique inbound references. + """ + s = S.query("match", target_release_ident=ident) + unique_source_idents = set() + for hit in s.scan(): + unique_source_idents.add(hit["source_release_ident"]) + return list(unique_source_idents) + +queue = set([seed]) +i = 0 +edges = set() +while queue: + node = queue.pop() + i += 1 + if i == max_nodes: + break + for n in unique_sources(node)[:5]: + if n == node: + print("skipping self ref: {}".format(n), file=sys.stderr) + continue + edges.add((node, n)) + queue.add(n) + +nodes = set() +for a, b in edges: + nodes.add(a) + nodes.add(b) + +print("digraph G {") +# add sensible labels +for n in nodes: + print(""" "{}" [label="{}"]; """.format(n, get_dot_label(n))) + +for a, b in edges: + print(""" "{}" -> "{}"; """.format(a, b)) +print("}") + diff --git a/skate/.gitignore b/skate/.gitignore index 4e893a0..031329a 100644 --- a/skate/.gitignore +++ b/skate/.gitignore @@ -24,4 +24,4 @@ /skate-wikipedia-doi packaging/debian/skate/usr skate_*_amd64.deb - +/skate-dot diff --git a/skate/Makefile b/skate/Makefile index ccaf08e..fc36c8e 100644 --- a/skate/Makefile +++ b/skate/Makefile @@ -1,5 +1,5 @@ SHELL := /bin/bash -TARGETS := skate-ref-to-release skate-derive-key skate-cluster skate-verify skate-to-doi skate-bref-id skate-from-unstructured skate-wikipedia-doi +TARGETS := skate-ref-to-release skate-derive-key skate-cluster skate-verify skate-to-doi skate-bref-id skate-from-unstructured skate-wikipedia-doi skate-dot PKGNAME := skate .PHONY: test diff --git a/skate/cmd/skate-dot/main.go b/skate/cmd/skate-dot/main.go new file mode 100644 index 0000000..97b70ad --- /dev/null +++ b/skate/cmd/skate-dot/main.go @@ -0,0 +1,80 @@ +// skate-dot generates dot files from inbound and outbound citation links. +package main + +import ( + "context" + "flag" + "fmt" + "io" + "log" + "os" + + "github.com/elastic/go-elasticsearch/esapi" + elasticsearch "github.com/elastic/go-elasticsearch/v7" +) + +var ( + es = flag.String("es", "http://localhost:9200", "elasticsearch holding fatcat_ref index") + index = flag.String("x", "fatcat_ref_v01", "index name") + fatcat = flag.String("f", "https://api.fatcat.wiki/v0", "fatcat api") + ident = flag.String("i", "2kw3xjf2cbcmdlm3ihkoz2t4lu", "release ident") +) + +func main() { + flag.Parse() + // s := "The Determination of Concentration and Type of Ownership on Bank Performance and Risks in Indonesia" + // fmt.Printf("%s\n", wordwrap.WrapString(s, 20)) + cfg := elasticsearch.Config{ + Addresses: []string{ + *es, + }, + } + es, err := elasticsearch.NewClient(cfg) + if err != nil { + log.Fatal(err) + } + client := &Client{ + Api: *fatcat, + Es: es, + Index: *index, + } + log.Println(client) + client.Outbound(*ident) + client.Inbound(*ident) +} + +// A client for fatcat and elasticsearch. +type Client struct { + Api string + Es *elasticsearch.Client + Index string +} + +func (c *Client) String() string { + info, _ := c.Es.Info() + return fmt.Sprintf("%s %s (%s) %s", c.Api, info, elasticsearch.Version, c.Index) +} + +func (c *Client) Inbound(ident string) []string { + resp, err := esapi.Search( + esapi.Search.WithContext(context.Background()), + esapi.Search.WithIndex(c.Index), + ) + if err != nil { + log.Fatal(err) + } + io.Copy(os.Stdout, resp.Body) + return nil +} + +func (c *Client) Outbound(ident string) []string { + req := &esapi.SearchRequest{ + Query: fmt.Sprintf("source_release_ident:%s", ident), + } + resp, err := req.Do(context.Background(), c.Es) + if err != nil { + log.Fatal(err) + } + io.Copy(os.Stdout, resp.Body) + return nil +} diff --git a/skate/go.mod b/skate/go.mod index e8678c0..c14fd53 100644 --- a/skate/go.mod +++ b/skate/go.mod @@ -5,6 +5,8 @@ go 1.15 require ( github.com/colinmarc/hdfs v1.1.3 // indirect github.com/dgraph-io/ristretto v0.0.3 + github.com/elastic/go-elasticsearch v0.0.0 // indirect + github.com/elastic/go-elasticsearch/v7 v7.12.0 // indirect github.com/golang/protobuf v1.5.2 // indirect github.com/json-iterator/go v1.1.10 github.com/kr/pretty v0.2.1 // indirect diff --git a/skate/go.sum b/skate/go.sum index 8690252..1d77ab9 100644 --- a/skate/go.sum +++ b/skate/go.sum @@ -11,6 +11,10 @@ github.com/dgraph-io/ristretto v0.0.3 h1:jh22xisGBjrEVnRZ1DVTpBVQm0Xndu8sMl0CWDz github.com/dgraph-io/ristretto v0.0.3/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/elastic/go-elasticsearch v0.0.0 h1:Pd5fqOuBxKxv83b0+xOAJDAkziWYwFinWnBO0y+TZaA= +github.com/elastic/go-elasticsearch v0.0.0/go.mod h1:TkBSJBuTyFdBnrNqoPc54FN0vKf5c04IdM4zuStJ7xg= +github.com/elastic/go-elasticsearch/v7 v7.12.0 h1:j4tvcMrZJLp39L2NYvBb7f+lHKPqPHSL3nvB8+/DV+s= +github.com/elastic/go-elasticsearch/v7 v7.12.0/go.mod h1:OJ4wdbtDNk5g503kvlHLyErCgQwwzmDtaFC4XyOxXA4= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= diff --git a/skate/wordwrap/wordwrap.go b/skate/wordwrap/wordwrap.go new file mode 100644 index 0000000..f7bedda --- /dev/null +++ b/skate/wordwrap/wordwrap.go @@ -0,0 +1,83 @@ +package wordwrap + +import ( + "bytes" + "unicode" +) + +const nbsp = 0xA0 + +// WrapString wraps the given string within lim width in characters. +// +// Wrapping is currently naive and only happens at white-space. A future +// version of the library will implement smarter wrapping. This means that +// pathological cases can dramatically reach past the limit, such as a very +// long word. +func WrapString(s string, lim uint) string { + // Initialize a buffer with a slightly larger size to account for breaks + init := make([]byte, 0, len(s)) + buf := bytes.NewBuffer(init) + + var current uint + var wordBuf, spaceBuf bytes.Buffer + var wordBufLen, spaceBufLen uint + + for _, char := range s { + if char == '\n' { + if wordBuf.Len() == 0 { + if current+spaceBufLen > lim { + current = 0 + } else { + current += spaceBufLen + spaceBuf.WriteTo(buf) + } + spaceBuf.Reset() + spaceBufLen = 0 + } else { + current += spaceBufLen + wordBufLen + spaceBuf.WriteTo(buf) + spaceBuf.Reset() + spaceBufLen = 0 + wordBuf.WriteTo(buf) + wordBuf.Reset() + wordBufLen = 0 + } + buf.WriteRune(char) + current = 0 + } else if unicode.IsSpace(char) && char != nbsp { + if spaceBuf.Len() == 0 || wordBuf.Len() > 0 { + current += spaceBufLen + wordBufLen + spaceBuf.WriteTo(buf) + spaceBuf.Reset() + spaceBufLen = 0 + wordBuf.WriteTo(buf) + wordBuf.Reset() + wordBufLen = 0 + } + + spaceBuf.WriteRune(char) + spaceBufLen++ + } else { + wordBuf.WriteRune(char) + wordBufLen++ + + if current+wordBufLen+spaceBufLen > lim && wordBufLen < lim { + buf.WriteRune('\n') + current = 0 + spaceBuf.Reset() + spaceBufLen = 0 + } + } + } + + if wordBuf.Len() == 0 { + if current+spaceBufLen <= lim { + spaceBuf.WriteTo(buf) + } + } else { + spaceBuf.WriteTo(buf) + wordBuf.WriteTo(buf) + } + + return buf.String() +} diff --git a/skate/wordwrap/wordwrap_test.go b/skate/wordwrap/wordwrap_test.go new file mode 100644 index 0000000..98010eb --- /dev/null +++ b/skate/wordwrap/wordwrap_test.go @@ -0,0 +1,99 @@ +package wordwrap + +import ( + "strings" + "testing" +) + +func TestWrapString(t *testing.T) { + cases := []struct { + Input, Output string + Lim uint + }{ + // A simple word passes through. + { + "foo", + "foo", + 4, + }, + // A single word that is too long passes through. + // We do not break words. + { + "foobarbaz", + "foobarbaz", + 4, + }, + // Lines are broken at whitespace. + { + "foo bar baz", + "foo\nbar\nbaz", + 4, + }, + // Lines are broken at whitespace, even if words + // are too long. We do not break words. + { + "foo bars bazzes", + "foo\nbars\nbazzes", + 4, + }, + // A word that would run beyond the width is wrapped. + { + "fo sop", + "fo\nsop", + 4, + }, + // Do not break on non-breaking space. + { + "foo bar\u00A0baz", + "foo\nbar\u00A0baz", + 10, + }, + // Whitespace that trails a line and fits the width + // passes through, as does whitespace prefixing an + // explicit line break. A tab counts as one character. + { + "foo\nb\t r\n baz", + "foo\nb\t r\n baz", + 4, + }, + // Trailing whitespace is removed if it doesn't fit the width. + // Runs of whitespace on which a line is broken are removed. + { + "foo \nb ar ", + "foo\nb\nar", + 4, + }, + // An explicit line break at the end of the input is preserved. + { + "foo bar baz\n", + "foo\nbar\nbaz\n", + 4, + }, + // Explicit break are always preserved. + { + "\nfoo bar\n\n\nbaz\n", + "\nfoo\nbar\n\n\nbaz\n", + 4, + }, + // Complete example: + { + " This is a list: \n\n\t* foo\n\t* bar\n\n\n\t* baz \nBAM ", + " This\nis a\nlist: \n\n\t* foo\n\t* bar\n\n\n\t* baz\nBAM", + 6, + }, + // Multi-byte characters + { + strings.Repeat("\u2584 ", 4), + "\u2584 \u2584" + "\n" + + strings.Repeat("\u2584 ", 2), + 4, + }, + } + + for i, tc := range cases { + actual := WrapString(tc.Input, tc.Lim) + if actual != tc.Output { + t.Fatalf("Case %d Input:\n\n`%s`\n\nExpected Output:\n\n`%s`\n\nActual Output:\n\n`%s`", i, tc.Input, tc.Output, actual) + } + } +} |