pi-openui 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +35 -0
- package/LICENSE +21 -0
- package/README.md +200 -2
- package/package.json +54 -4
- package/src/blocks/braille.ts +121 -0
- package/src/blocks/bubble.ts +30 -0
- package/src/blocks/charts.ts +370 -0
- package/src/blocks/code.ts +101 -0
- package/src/blocks/core.ts +343 -0
- package/src/blocks/diagrams.ts +142 -0
- package/src/blocks/geo.ts +206 -0
- package/src/blocks/interact.ts +252 -0
- package/src/blocks/markdown.ts +135 -0
- package/src/blocks/notes.ts +277 -0
- package/src/blocks/render.ts +148 -0
- package/src/blocks/sequence.ts +266 -0
- package/src/blocks/table.ts +70 -0
- package/src/blocks/types.ts +126 -0
- package/src/blocks/util.ts +171 -0
- package/src/data/land.ts +3 -0
- package/src/data/sample-image.ts +67 -0
- package/src/diagram/canvas.ts +182 -0
- package/src/diagram/dag.ts +174 -0
- package/src/diagram/decode.ts +241 -0
- package/src/diagram/erd.ts +190 -0
- package/src/diagram/infra.ts +444 -0
- package/src/diagram/layered.ts +334 -0
- package/src/diagram/layeredDiagram.ts +350 -0
- package/src/diagram/palette.ts +209 -0
- package/src/diagram/render.ts +60 -0
- package/src/diagram/router.ts +402 -0
- package/src/diagram/wires.ts +271 -0
- package/src/lang/docs.ts +575 -0
- package/src/lang/library.ts +613 -0
- package/src/lang/md.ts +47 -0
- package/src/lang/parse.ts +230 -0
- package/src/lang/samples.ts +227 -0
- package/src/pi/extension.ts +190 -0
- package/src/pi/images.ts +185 -0
- package/src/pi/widget.ts +562 -0
package/src/data/land.ts
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
// Generated by scripts/gen-land.mjs from Natural Earth 110m land (public domain). Do not edit.
|
|
2
|
+
// Rings separated by "|", points by ";", first point absolute then deltas, units of 0.1 degree: x=(lon+180)*10, y=(90-lat)*10.
|
|
3
|
+
export const LAND = "1204,1700;-3,5;-3,5;-21,-1;-22,0;-12,-3;0,-1;-6,-2;23,0;21,1;8,-4;5,-4;10,4|208,1695;-19,1;-13,-3;-6,-4;-1,0;-6,-3;6,-4;19,2;10,3;7,3;3,5|1348,1680;13,5;4,6;1,4;1,5;-16,3;-16,3;-19,2;-21,2;-24,0;-13,-4;2,-4;21,-3;9,-3;6,-4;5,-4;6,-3;6,-5;5,0;15,-2;15,2|588,1635;13,2;12,-2;-6,3;-9,3;-14,-1;-10,-3;2,-4;12,2|544,1635;16,4;-6,-1;-13,-1;-14,-2;7,-3;10,3|810,1619;11,2;11,-1;6,5;-8,-1;-12,1;-12,-1;-14,1;-10,-2;-5,-4;6,-2;13,2;14,0|1115,1610;2,4;-2,4;-3,4;-12,1;-11,2;-13,0;5,-4;-12,1;-11,2;-8,-3;0,-4;11,-4;7,-1;11,0;3,-5;1,-4;0,-8;5,-5;9,-1;6,4;2,3;4,5;4,4;2,5|0,1747;1,0;8,-6;18,4;2,-1;2,-1;4,-1;3,-1;1,0;2,0;1,0;14,4;13,-4;2,0;29,-2;10,2;5,1;15,4;28,2;23,3;38,3;29,-3;43,2;24,3;26,-3;28,-3;2,-4;-39,-1;-33,-2;-8,-4;-27,-2;2,-5;4,-4;3,-3;-2,-5;-16,-2;-8,-4;-15,-3;24,1;23,-2;15,3;17,-3;17,-3;8,-4;-4,-4;-13,-2;-14,-3;-21,-1;-18,-1;-19,-1;-7,-4;-13,-3;-8,-4;-3,-11;5,1;9,3;17,-1;16,-1;8,4;16,-1;13,-2;13,-3;11,-3;15,-1;0,-4;-4,-4;3,-3;13,-2;6,3;15,-2;12,-2;14,0;13,-1;14,-3;11,-2;12,-2;8,1;7,0;14,-1;14,2;13,0;14,-2;13,1;15,1;14,0;14,0;15,0;14,0;10,-3;12,-2;13,2;12,-1;11,-4;6,3;4,4;6,3;10,-3;12,4;14,1;11,3;15,-1;12,-2;15,1;14,1;14,2;5,-4;-7,-4;-5,-3;-12,-1;-6,-4;-2,-3;-4,-8;8,2;13,0;13,0;12,1;10,3;4,4;14,0;13,-1;13,-2;13,-1;10,2;13,-1;9,-7;8,4;11,2;13,-1;8,4;13,0;12,1;12,3;8,-4;4,-4;10,4;14,-1;10,2;7,4;13,-1;10,-2;11,-3;12,-1;14,-2;13,-1;9,-2;6,-3;3,-5;-2,-4;-3,-4;-3,-3;-3,-4;-3,-4;0,-4;1,-4;4,-3;4,-5;2,-3;-2,-5;-1,-4;4,-4;6,-3;6,-4;7,-3;8,-3;4,-4;6,-3;6,-3;10,0;6,-3;7,-2;8,-1;7,-3;6,-3;8,-1;6,2;-4,4;-10,3;-4,2;-8,-2;-8,1;-7,2;-7,3;-5,3;-1,4;0,4;5,3;-7,2;-9,1;-6,3;-6,3;-6,5;-2,4;4,4;5,3;8,2;8,3;4,4;2,4;3,4;5,3;3,4;1,9;3,4;1,4;3,4;-1,5;-6,4;-6,3;-13,2;-4,3;-7,4;-15,3;-13,2;-12,2;-14,2;-8,4;-16,1;-18,-1;-16,1;-16,0;3,4;15,2;11,3;6,3;-11,3;-17,-1;-14,3;-1,4;0,4;12,3;2,4;12,4;22,1;18,3;14,3;18,3;25,2;24,2;17,3;19,4;10,4;5,4;12,-3;16,-3;18,-3;21,-3;17,-3;25,0;25,1;20,3;6,-4;14,-3;26,-1;19,-2;19,-2;21,-1;22,-2;15,-3;-7,-3;-4,-4;0,-3;-19,0;-21,2;-19,0;-3,-4;1,-8;5,-2;14,-2;17,-2;12,-3;12,-3;9,-4;14,-2;13,-1;7,-1;16,-1;14,-1;13,-2;12,-2;11,-3;14,-3;9,-3;9,-3;3,-4;-11,-2;4,-4;7,-4;10,-1;11,-3;10,-3;8,-4;5,-5;7,-2;12,0;5,4;12,0;0,-4;5,-4;11,1;3,4;12,1;13,-2;12,-1;11,0;5,4;11,-3;10,-2;11,-1;11,-1;11,-3;11,-1;8,-3;6,-3;8,2;10,-1;8,5;5,3;12,-2;4,-4;10,-2;13,0;4,4;8,-4;11,-1;12,0;11,0;11,1;11,1;4,3;7,3;11,-2;11,0;12,0;11,0;10,-2;11,-1;8,-3;10,-1;10,-1;8,-3;5,-6;6,-3;10,2;4,3;9,2;10,0;7,3;7,3;11,-3;3,-4;9,-2;11,-3;9,-1;12,-2;8,-2;8,-3;8,-2;9,1;9,-3;7,-3;9,0;9,-2;1,-4;9,-3;8,-1;10,-2;9,-1;9,1;10,1;8,2;1,5;8,3;6,3;12,1;7,3;8,3;10,0;8,-2;9,-4;9,2;10,1;9,2;10,0;10,0;8,11;0,2;-1,5;-10,2;-8,4;1,4;12,0;-2,4;-5,3;-5,5;8,3;12,1;11,-2;6,-4;3,-4;6,-3;6,-3;2,-3;6,-5;6,-1;11,-1;10,-1;10,-1;5,-4;3,-4;7,-4;10,-2;8,-2;6,-4;6,-1;7,-2;10,1;9,-1;10,-1;11,0;7,-2;5,-7;4,3;4,5;9,1;9,1;10,-1;10,1;9,0;7,-1;8,1;8,2;9,-2;11,0;9,-1;10,1;7,-3;5,-3;7,-3;12,-7;7,1;7,3;7,3;13,6;10,1;9,0;11,-2;10,-1;9,-3;6,-3;12,0;7,-2;8,2;5,3;7,3;11,0;7,2;12,3;12,1;11,-1;8,-3;6,-3;9,-1;9,1;11,1;9,-1;9,0;9,1;9,1;9,-2;11,-2;10,0;11,0;10,-1;9,-1;2,-5;1,-4;6,3;2,4;3,4;4,4;9,2;11,-1;13,0;9,-1;13,0;10,0;13,0;11,1;7,3;-2,4;6,3;11,2;11,3;13,2;14,1;10,2;11,0;7,-3;9,2;7,3;9,3;12,1;12,1;5,4;11,2;8,4;11,1;11,0;11,1;12,0;12,0;11,2;11,2;10,2;7,3;-1,4;-5,3;-5,5;-3,3;-5,5;-13,1;-6,4;-13,2;-5,4;-6,3;-8,4;-4,4;-2,3;-1,5;0,4;6,4;2,3;4,4;19,1;4,5;-18,1;-15,2;-19,1;-9,5;-2,5;-4,4;-5,3;13,4;5,4;9,4;12,3;14,3;15,3;23,3;5,5;29,2;2,1;7,3;28,-2;23,3;17,2|1122,1438;13,7;14,2;-4,5;-10,0;-5,-3;-3,4;-8,3;-11,-1;-8,-3;-10,-1;-13,-6;-10,-5;-14,-12;9,2;14,7;13,4;5,-5;3,-7;10,-4;7,1;3,5;5,7|1215,1411;8,4;-3,4;-14,3;-4,-4;-9,5;-5,-5;12,-5;8,2;7,-4|2503,1397;-16,1;0,-6;2,-4;0,-2;7,3;9,2;1,2;-3,4|3254,1308;10,3;5,-1;8,-2;6,1;1,12;-4,3;-1,8;-3,-3;-7,7;-2,0;-7,-1;-6,-8;-1,-7;-6,-8;0,-5;7,1|3530,1309;2,4;8,-4;2,4;0,5;-3,4;-7,8;-5,4;4,5;-8,0;-8,3;-3,7;-6,10;-8,5;-5,2;-9,0;-6,-3;-11,-1;-2,-3;5,-8;13,-10;6,-2;8,-3;8,-6;6,-5;5,-7;4,-3;1,-5;7,-5;2,4|3546,1262;7,10;1,-7;4,3;2,8;8,3;6,1;6,-4;5,1;-2,9;-3,6;-8,-1;-3,3;1,5;-1,2;-4,5;-5,7;-8,4;-1,-3;-4,-1;5,-8;-3,-6;-11,-4;1,-4;7,-3;1,-8;0,-6;-4,-7;0,-2;-5,-4;-7,-9;-5,-7;4,0;6,5;7,3;3,9|3471,1122;-4,2;-5,-3;-7,-4;-7,-6;-6,-7;-2,-3;5,0;5,4;5,3;3,3;8,6;5,5|3584,1073;3,3;-1,6;-7,1;-5,-1;-1,-5;4,-3;4,1;3,-2|0,1066;-6,2;-7,2;-1,-4;5,-2;3,0;6,-3;2,-1;-1,5;-1,1|3478,1065;-3,1;-3,-4;0,-3;6,6|3471,1049;2,8;-3,-1;-2,1;-1,-3;-1,-8;5,3|2301,1036;1,12;3,4;-1,5;-2,3;-3,-6;-2,3;2,8;-1,4;-3,2;-1,9;-4,11;-5,14;-6,19;-4,14;-4,11;-8,3;-9,4;-6,-3;-8,-3;-2,-5;-1,-9;-4,-8;0,-7;1,-8;5,-1;0,-4;5,-7;1,-7;-3,-4;-2,-7;0,-9;3,-5;1,-7;5,0;6,-2;4,-2;4,0;6,-6;8,-6;3,-5;-1,-4;4,1;5,-7;1,-6;3,-5;3,5;3,4;3,7|3236,1038;3,7;7,-3;3,4;5,4;-1,4;2,9;1,5;3,1;3,9;-1,5;3,7;11,5;7,5;6,4;-1,2;6,7;4,10;4,-2;4,5;2,-2;2,11;7,6;5,4;8,8;2,8;1,5;-1,7;5,8;-1,9;-2,5;-2,9;0,5;-2,7;-5,10;-7,4;-4,8;-3,5;-3,9;-4,5;-2,7;-2,7;1,3;-6,4;-11,0;-9,4;-5,4;-6,4;-8,-4;-6,-2;1,-5;-5,2;-9,7;-9,-3;-5,-1;-6,-1;-10,-3;-6,-6;-2,-8;-2,-5;-5,-4;-10,-1;3,-5;-2,-7;-5,7;-9,2;6,-6;1,-6;4,-5;-1,-7;-8,9;-6,3;-4,8;-8,-4;0,-6;-6,-7;-5,-4;2,-2;-13,-6;-7,0;-10,-5;-18,1;-13,3;-11,4;-10,-1;-10,5;-9,3;-2,5;-3,4;-9,0;-6,1;-9,-2;-7,1;-7,1;-6,5;-3,0;-5,2;-5,4;-7,-1;-7,0;-10,-6;-6,-2;0,-6;5,-1;2,-2;0,-4;1,-7;-1,-6;-5,-10;-2,-6;0,-5;-4,-7;0,-3;-4,-4;-2,-8;-5,-8;-2,-4;5,4;-4,-9;5,3;3,4;0,-5;-5,-8;-1,-3;-2,-3;1,-6;2,-2;1,-5;-1,-6;4,-7;1,7;4,-7;9,-3;4,-4;8,-4;5,-1;2,1;8,-3;6,-1;2,-3;3,0;5,0;11,-3;5,-5;3,-5;5,-5;1,-4;0,-5;7,-9;4,9;5,-2;-4,-5;3,-5;5,2;1,-7;5,-5;3,-4;5,-2;0,-3;4,1;0,-2;5,-1;5,-2;7,5;6,6;6,0;6,1;-2,-6;5,-8;4,-2;-1,-3;4,-6;6,-3;5,1;9,-2;0,-5;-8,-3;6,-2;6,3;6,4;8,2;3,-1;6,3;6,-2;4,0;2,-1;5,5;-3,5;-4,4;-3,0;1,4;-3,5;-4,5;1,3;8,6;8,3;5,3;7,6;3,0;5,3;2,3;9,3;7,-3;2,-6;2,-4;1,-6;3,-8;-1,-4;0,-3;-1,-6;2,-8;1,-2;-1,-3;2,-5;2,-6;0,-3;4,-3;3,5;1,6;2,1;1,4;3,5;1,6;0,4|3421,1005;3,3;-7,0;-4,-6;6,2;2,1|3007,1002;-4,1;-13,-7;9,-2;5,3;4,3;-1,2|3409,999;-4,0;-6,-1;-3,-2;1,-4;7,2;3,2;2,3|3417,996;-2,2;-7,-9;-2,-6;3,0;4,8;4,5|3044,1001;-8,3;-1,-2;1,-3;4,-6;10,-4;1,-2;8,-3;7,0;4,-1;3,1;-3,3;-11,4;-8,3;-7,7|2979,981;4,3;6,-1;2,4;-11,2;-7,1;-6,0;4,-5;5,-1;3,-3|3029,981;-1,6;-15,2;-14,-1;0,-4;8,-2;6,3;7,0;9,-4|3399,983;0,2;-8,-4;-5,-3;-4,-4;2,-1;4,3;8,4;3,3|3375,973;-2,1;-4,-2;-4,-4;0,-2;6,4;4,3|2886,968;19,1;3,-4;18,4;4,7;15,2;12,6;-11,4;-11,-5;-9,1;-11,-1;-9,-2;-12,-4;-7,-1;-4,2;-18,-4;-2,-5;-9,0;7,-10;12,1;8,3;4,1;1,4|3147,962;-5,7;-1,-8;2,-3;2,-4;2,3;0,5|3359,968;-3,1;-4,-4;-5,-6;-2,-8;2,-1;1,3;3,3;4,6;5,3;-1,3|3320,955;-5,1;-2,2;-5,3;-6,2;-5,0;-8,-3;-6,-3;1,-3;9,2;5,-1;2,-5;1,0;1,5;6,0;3,-4;5,-3;-1,-6;6,-1;2,2;0,6;-3,6|3072,935;-3,3;-7,-2;-2,-4;10,-1;2,4|3105,931;3,8;-8,-5;-8,0;-6,0;-7,0;2,-6;13,0;11,3|3331,945;-3,3;-2,-6;-2,-4;-4,-3;-6,-5;-7,-3;2,-2;6,3;3,2;4,2;4,5;4,3;1,5|3141,912;3,16;11,6;8,-11;11,-6;9,0;9,4;7,3;11,2;17,7;19,6;7,5;5,5;2,6;16,6;3,5;-9,1;2,7;9,6;6,11;6,0;0,4;7,2;-3,2;11,4;-1,3;-7,1;-2,-3;-9,-1;-10,-2;-8,-6;-5,-6;-6,-8;-13,-5;-8,3;-6,3;1,8;-8,3;-5,-1;-11,-1;-9,-8;-10,-2;-2,3;-13,0;4,-8;7,-3;-3,-11;-5,-8;-19,-9;-8,0;-15,-10;-3,5;-4,1;-2,-4;0,-4;-8,-5;11,-3;7,0;-1,-3;-15,0;-4,-6;-9,-2;-4,-5;14,-2;5,-3;16,4;1,4|3052,886;-8,10;-7,2;-10,-2;-16,0;-9,2;-2,7;9,9;6,-4;18,-4;0,5;-5,-2;-4,6;-9,4;10,13;-2,3;9,12;0,6;-6,3;-4,-3;5,-8;-10,4;-2,-3;1,-4;-7,-6;1,-10;-7,3;1,12;0,14;-6,2;-4,-3;3,-9;-2,-10;-4,0;-3,-7;4,-7;1,-7;5,-16;2,-4;9,-7;8,3;12,1;12,0;10,-7;1,2|3087,889;-1,8;-5,-1;-1,7;4,5;-3,1;-4,-6;-3,-13;2,-8;3,-4;1,6;6,1;1,4|2858,959;-11,0;-8,-9;-13,-8;-4,-6;-8,-8;-5,-7;-8,-14;-8,-9;-3,-8;-4,-8;-9,-7;-5,-8;-8,-6;-10,-11;-1,-5;6,1;16,2;9,9;7,7;6,4;9,11;11,0;8,7;6,8;7,5;-4,8;6,4;4,0;1,7;4,5;7,1;5,7;-2,12;-1,16|2979,882;11,9;-12,1;-3,7;0,9;-9,7;-1,10;-4,15;-1,-3;-11,4;-4,-6;-7,-1;-5,-3;-12,4;-4,-5;-7,0;-8,-1;-1,-13;-5,-3;-5,-8;-1,-9;1,-9;6,-7;7,3;8,-2;2,-8;4,-2;12,-2;7,-8;5,-6;4,-4;9,-5;7,-7;5,-8;4,0;5,5;1,4;6,3;9,3;-1,4;-7,0;2,5;-7,4;-6,9;7,9;-1,5|3064,816;1,6;0,6;-3,9;-4,-10;-4,5;3,8;-3,4;-12,-6;-3,-7;3,-5;-6,-4;-3,4;-5,-1;-7,6;-2,-3;4,-8;6,-3;6,-4;3,5;8,-3;2,-5;7,0;-1,-8;8,5;1,5;1,4|2612,838;-9,2;-4,-8;-2,-14;4,-16;7,5;5,7;5,11;-2,10;-4,3|1191,799;-9,1;-2,-1;3,-3;0,-4;6,-1;2,0;0,8|3040,797;-4,4;-3,6;-3,3;-6,-7;2,-3;2,-3;1,-6;6,0;-2,6;8,-9;-1,9|2985,807;-13,9;5,-7;7,-6;6,-7;5,-10;2,8;-7,6;-5,7|3019,781;6,3;6,0;0,4;-5,5;-6,3;0,-5;0,-5;-1,-5|3055,778;3,12;-8,-3;0,3;3,6;-5,3;0,-7;-3,-1;-2,-6;6,1;0,-4;-6,-8;9,1;3,3|3015,769;-2,9;-5,-5;-5,-8;9,1;3,3|3013,715;6,3;3,-3;1,3;-1,4;3,7;-2,8;-6,4;-2,8;2,8;6,1;4,-1;13,5;-1,6;3,2;-1,5;-8,-5;-4,-6;-2,4;-7,-6;-9,2;-5,-3;1,-4;3,-2;-3,-3;-1,4;-5,-6;-2,-4;0,-10;4,4;1,-16;3,-9;6,0|1144,718;-2,2;-8,0;-6,1;0,-5;1,-1;8,0;5,1;2,2|1031,721;-3,2;-6,-2;-5,-3;1,-3;4,0;2,0;7,1;5,2;2,3;-7,0|1074,701;9,2;1,-2;8,0;6,3;2,0;2,3;6,0;-1,3;5,0;5,4;-4,4;-5,-2;-4,0;-4,0;-1,2;-4,0;-2,-2;-3,1;-4,7;-3,-2;0,-2;-7,-2;-4,1;-7,-1;-4,2;-6,-3;1,-4;10,2;7,1;4,-3;-5,-4;0,-4;-6,-1;2,-3;6,0|2903,713;-8,5;-8,-3;-1,-9;5,-4;11,-3;6,0;2,4;-4,4;-3,6|245,709;-2,2;-2,-2;0,-2;-2,-4;1,-1;1,-2;0,-2;0,-1;1,1;4,1;2,1;1,1;3,4;-4,3;-3,1|239,694;-3,0;-2,-2;-1,-1;1,-1;3,1;3,1;-1,2|232,688;0,1;-5,0;0,-1;5,0|223,687;-1,0;-3,0;-2,-2;0,-1;3,-1;1,0;2,4|207,680;-2,1;-3,-2;1,0;1,-1;2,0;1,2|1003,672;4,4;10,-1;3,2;9,6;6,5;3,0;6,2;-1,3;8,0;7,4;-1,2;-7,2;-6,0;-7,-1;-15,1;7,-5;-4,-3;-6,0;-4,-3;-2,-6;-6,0;-9,-2;-3,-2;-13,-2;-4,-2;4,-2;-10,-1;-7,5;-4,0;-2,3;-4,1;-5,-1;6,-3;2,-4;4,-2;5,-2;8,-1;2,-1;9,1;8,0;9,3|1025,662;-3,1;-2,-6;-4,-3;2,-6;3,0;4,9;0,5|3012,672;-5,8;-5,-8;-1,-8;6,-9;8,-8;5,3;-2,6;-6,16|1022,634;-11,2;-1,-4;5,-1;7,1;0,2|1030,634;-2,7;-2,-1;1,-5;-5,-4;0,-1;8,4|3146,559;2,3;-6,6;-4,-3;-5,2;-3,6;-6,-3;0,-5;5,-6;6,2;4,-5;7,3|2146,543;-7,5;1,1;0,1;-10,4;-5,-1;-2,-4;4,0;1,0;1,-3;8,0;9,-3|2037,543;5,3;8,0;8,0;-1,2;6,-1;-1,3;-15,1;0,-2;-12,-2;2,-4|1955,518;-3,8;1,3;-2,5;-8,-4;-5,-1;-14,-5;2,-5;11,1;11,-1;7,-1|1892,488;6,7;-1,13;-5,0;-4,3;-4,-3;0,-12;-2,-6;5,1;5,-3|3210,529;-4,8;2,5;-5,7;-13,4;-18,1;-14,11;-7,-3;0,-8;-18,2;-11,5;-12,0;10,8;-7,16;-6,5;-5,-4;2,-9;-6,-3;-4,-7;10,-3;5,-6;10,-6;7,-6;20,-3;11,2;10,-18;7,5;15,-10;5,-4;7,-12;-2,-12;4,-6;11,-2;5,14;0,8;-9,10;0,11|1896,478;-4,8;-4,-2;-3,-7;2,-3;7,-4;2,8|3239,458;7,2;7,-4;2,11;-14,3;-9,10;-16,-7;-5,11;-11,0;-2,-10;5,-7;11,-1;3,-14;3,-8;11,11;8,3|1163,435;8,1;9,0;-5,4;-4,0;-12,-4;-3,-3;4,-3;3,5|1182,409;-5,0;-13,-3;-9,-5;3,-1;13,3;11,4;0,2|565,415;-5,1;-17,-4;-3,-4;-8,-3;-2,-3;-11,-2;-3,-5;0,-3;11,2;6,2;9,1;4,4;5,4;10,4;4,6|1239,393;-7,9;7,-3;6,2;-3,3;9,3;4,-3;10,4;-3,7;7,-2;1,5;4,7;-5,8;-4,1;-7,-2;2,-8;-2,-2;-12,9;-6,0;7,-5;-10,-2;-10,0;-20,0;-1,-3;6,-4;-4,-2;8,-6;10,-16;7,-6;8,-3;5,0;-2,3;-5,6|473,360;10,-1;-4,11;9,8;-4,0;-6,-4;-4,-5;-5,-3;-1,-5;0,-3;5,2|3236,393;11,17;-15,-3;-6,14;9,11;0,7;-8,-6;-6,7;-2,-8;1,-10;-1,-11;2,-7;1,-14;-6,-9;1,-14;9,-5;-4,-4;5,-2;2,7;4,10;-1,9;4,11|1732,377;-18,6;-14,-1;8,-11;-5,-10;14,-8;7,-4;9,-1;10,6;-5,7;2,7;-8,9|1927,344;-6,8;-11,-6;-1,-4;15,-3;3,5|270,329;-10,4;-5,-3;-2,-5;9,-3;6,-2;6,1;5,3;-9,5|1770,314;-11,10;10,-1;11,0;-2,8;-9,9;10,1;10,13;7,1;6,12;3,4;12,2;-1,6;-6,3;4,5;-9,5;-13,0;-17,3;-5,-2;-6,5;-9,-1;-7,3;-6,-2;15,-10;9,-2;-16,-2;-3,-4;11,-3;-6,-5;2,-7;15,1;2,-6;-7,-6;-12,-2;-3,-3;4,-4;-3,-3;-6,5;0,-10;-6,-5;4,-10;8,-8;8,0;12,0|144,301;-6,1;-6,-1;-7,-3;10,-2;8,1;1,4|1007,278;-4,6;-4,-1;-3,-3;1,-1;4,-3;4,0;2,2|981,273;-12,5;-7,0;-2,-3;8,-4;13,0;0,2|83,262;6,2;6,-1;8,3;10,1;-1,1;-7,2;-8,-2;-4,-2;-9,1;-2,-1;1,-4|948,243;2,5;5,-2;6,3;11,3;12,3;0,5;8,-1;7,4;-9,3;-15,-3;-6,-4;-10,5;-14,5;-4,-5;-13,1;8,-5;2,-8;3,-9;7,0|1655,235;-2,7;11,7;-13,7;-29,7;-9,2;-13,-1;-28,-4;10,-4;-22,-5;18,-2;0,-3;-21,-2;6,-7;16,-1;15,7;15,-6;13,3;16,-5;17,0|1041,229;-11,0;-2,-5;4,-5;9,-2;8,3;0,4;-1,2;-7,3|0,210;25,8;26,10;-1,6;7,3;-3,-8;27,2;20,9;-10,5;-16,1;-1,9;-4,2;-9,0;-8,-3;-13,-3;-2,-5;-10,-1;-12,1;-5,-3;2,-4;-12,2;5,5;-6,4;-13,5;-13,-1;9,5;6,8;5,3;1,4;-3,3;-18,-2;-28,7;-9,1;-16,8;-14,6;-4,4;-14,-7;-26,8;-5,-4;-9,5;-14,-2;-3,7;-12,10;1,4;11,2;-1,14;-10,1;-4,8;4,4;-17,6;-4,11;-15,2;-3,11;-14,9;-4,-7;-4,-15;-6,-22;5,-14;9,-6;0,-4;16,-3;17,-12;18,-10;18,-8;8,-15;-12,1;-6,9;-26,11;-8,-13;-26,4;-25,16;8,7;-22,2;-15,1;0,-7;-15,-2;-13,5;-30,-1;-33,3;-32,19;-39,24;16,1;5,6;10,2;6,-5;11,1;14,11;1,9;-8,10;-1,12;-4,16;-15,14;-4,7;-13,12;-14,11;-6,6;-14,6;-6,0;-6,-5;-14,7;-1,4;-4,-1;-4,4;-3,3;0,7;-5,2;-2,2;-4,3;-6,2;-5,2;0,5;-1,1;4,1;6,5;8,12;3,6;0,12;-4,5;-9,2;-8,4;-9,1;-1,-5;2,-8;-5,-10;8,-2;-7,-8;-5,-2;-1,1;-3,1;-1,-2;-2,0;-3,-2;3,-4;2,-2;-1,-1;3,-6;-1,-2;-6,-1;-4,-2;-14,3;-8,4;-10,3;5,-5;-2,-4;8,-6;-6,-5;-8,3;-12,7;-6,6;-10,1;-5,5;6,6;8,2;0,5;8,2;11,-7;9,4;7,0;1,6;-14,2;-5,6;-9,5;-5,7;10,5;4,10;6,9;7,8;0,8;-6,2;2,6;6,3;-2,8;-2,8;-6,1;-7,10;-8,14;-9,12;-14,9;-14,8;-11,1;-6,5;-4,-3;-6,4;-14,5;-10,2;-4,11;-5,0;-3,-7;3,-4;-14,-3;-5,1;-13,9;-8,9;-2,7;7,11;10,13;9,6;6,8;4,19;-1,17;-8,7;-12,6;-8,9;-12,9;-4,-6;3,-7;-8,-6;-8,-1;-4,-6;-5,-10;-9,-4;-9,0;2,-8;-9,0;-1,11;-5,15;-3,8;0,8;7,0;4,9;2,9;5,5;6,2;5,5;3,1;6,6;4,6;0,7;-1,5;1,3;1,6;4,3;3,9;0,3;-7,1;-9,-8;-12,-8;-1,-5;-6,-6;-1,-9;-4,-5;1,-7;-2,-5;-4,-3;-2,-5;-5,-6;-5,-5;-2,6;-2,-5;2,-7;3,-9;-1,-8;3,-7;-4,-6;1,-11;-4,-5;-3,-12;-2,-13;-4,-8;-7,5;-11,7;-6,-1;-6,-2;3,-13;-2,-9;-8,-12;2,-3;-6,-2;-7,-8;-3,-5;-1,-5;-2,-5;-4,-6;-9,0;1,4;-3,6;-5,-2;-1,1;-3,-1;-4,-1;-1,4;-7,0;-12,2;0,8;-5,5;-14,7;-12,12;-7,6;-10,7;0,4;-5,3;-9,3;-5,1;-3,8;2,13;1,8;-4,9;0,17;-6,1;-4,8;3,3;-9,3;-4,6;-4,3;-9,-9;-5,-14;-4,-10;-3,-5;-5,-9;-3,-13;-2,-6;-9,-14;-4,-19;-3,-13;0,-12;-2,-10;-14,6;-7,-1;-13,-12;4,-4;-3,-3;-11,-9;-8,-2;-3,-8;-7,-7;-19,2;-16,0;-14,1;-19,-3;-11,-2;-11,-1;-4,-13;-5,-1;-8,1;-10,5;-12,-3;-10,-8;-10,-3;-6,-9;-8,-13;-5,1;-7,-3;-3,4;-6,-1;2,5;-1,2;3,7;4,9;5,2;2,4;7,4;0,4;-1,4;1,3;3,3;2,3;1,2;-1,-7;3,-5;3,-1;3,3;0,6;-2,6;2,4;2,-1;0,3;8,-2;8,0;6,1;7,-7;7,-6;7,-7;3,-3;1,1;-1,4;-1,2;1,8;4,7;6,3;7,2;6,1;5,6;2,3;4,2;0,2;-4,6;-1,3;-4,3;-4,7;-5,-1;-2,3;-1,5;1,6;-1,2;-5,0;-6,3;-1,5;-2,2;-6,0;-4,3;0,4;-5,3;-6,-1;-6,3;-5,0;-7,3;-2,5;0,3;-10,4;-16,5;-9,7;-5,1;-3,-1;-5,4;-7,2;-8,1;-3,0;-2,3;-3,0;-1,3;-5,0;-3,1;-7,0;-3,-6;1,-6;-2,-3;-2,-7;-3,-4;2,-1;-1,-4;1,-2;0,-4;-1,-5;-4,-3;0,-4;-5,-3;-6,-9;-3,-8;-7,-7;-4,-1;-7,-10;-1,-7;1,-6;-6,-11;-5,-4;-5,-2;-3,-6;0,-2;-3,-5;-3,-2;-3,-8;-7,-8;-5,-7;-5,0;2,-5;0,-4;2,-4;-1,-1;-3,4;-2,8;-2,5;-3,2;-3,-4;-5,-4;-7,-15;-1,1;4,11;6,10;8,16;4,5;3,6;9,11;-2,1;0,7;12,9;2,2;3,10;-2,2;1,10;4,12;4,2;5,4;6,12;3,9;5,5;14,9;5,6;6,6;3,3;5,3;2,3;0,4;-6,3;4,2;4,2;2,4;4,5;5,0;10,-3;10,-1;9,-3;5,-1;4,-2;5,0;4,0;4,-2;6,-1;4,-3;4,0;0,3;-1,5;0,6;-2,3;-2,11;-5,11;-6,13;-9,15;-9,11;-11,13;-10,9;-15,9;-10,8;-11,12;-2,5;-2,3;-7,4;-3,4;-3,1;-2,7;-3,4;-2,6;-4,4;-5,12;1,6;6,3;1,3;-3,6;1,3;-1,5;3,6;5,10;3,2;2,5;-1,10;2,8;0,16;2,5;-3,7;-4,7;-6,6;-10,4;-11,5;-11,11;-4,1;-7,8;-4,2;-1,7;5,8;2,5;0,3;2,0;-1,10;-1,4;2,2;-1,4;-5,4;-8,3;-12,6;-4,3;1,4;2,1;-1,5;-2,8;-1,8;-3,5;-7,5;-2,1;-4,5;-3,5;-5,7;-12,11;-7,6;-7,4;-11,4;-5,1;-1,2;-6,-1;-5,2;-11,-2;-6,1;-4,0;-11,4;-8,1;-6,4;-5,0;-4,-3;-3,-1;-5,-4;0,1;-2,-2;1,-6;-4,-7;3,-2;0,-7;-6,-10;-5,-8;-8,-13;-7,-8;-4,-7;-2,-10;-3,-7;-3,-15;0,-12;-1,-6;-4,-4;-5,-8;-6,-12;-2,-7;-8,-9;-1,-8;-1,-6;2,-9;3,-9;1,-5;3,-9;2,-4;6,-6;3,-5;1,-7;0,-6;-3,-3;-3,-6;-2,-6;0,-2;3,-4;-3,-10;-2,-7;-5,-6;1,-2;-1,-3;-3,-8;-8,-10;-10,-10;-7,-9;-6,-10;0,-3;2,-3;3,-8;2,-7;-2,-2;3,-11;2,-8;-4,-6;-5,-2;-2,-5;-2,-1;0,-3;-10,4;-4,-1;-4,3;-8,-1;-5,-6;-4,-7;-7,-7;-7,0;-9,0;-8,2;-8,2;-16,6;-6,3;-9,3;-9,-3;-4,0;-7,-2;-6,0;-12,2;-7,3;-10,4;-2,-1;-3,0;-10,-4;-9,-8;-9,-5;-6,-7;-3,-1;-7,-4;-5,-5;-2,-4;-1,-7;-5,-6;-4,-4;-2,-1;-3,-2;-1,-5;-1,-2;-3,-1;-6,-5;-4,0;-2,-3;0,-2;-3,-2;-1,-2;-1,-8;1,-4;-4,-8;-5,-3;4,-2;5,-7;2,-5;-1,-6;3,-5;2,-9;-2,-10;-1,-5;1,-5;-2,-5;-6,-4;1,-4;0,-5;4,-3;3,-5;0,-3;3,-7;6,-7;3,-1;3,-6;0,-5;4,-7;6,-3;7,-10;5,-4;9,-1;8,-7;5,-3;8,-8;-2,-13;4,-8;1,-6;6,-6;10,-5;8,-4;7,-10;3,-7;7,0;6,5;10,-1;10,2;4,0;10,-5;11,-2;6,-4;10,-3;17,-2;16,-1;5,2;10,-4;10,0;4,2;7,0;11,-5;7,2;0,5;8,-4;1,2;-5,5;0,5;3,2;-1,9;-6,5;1,5;6,0;2,5;4,2;12,3;4,-1;8,2;13,4;5,9;9,2;14,4;11,5;5,-2;5,-5;-3,-8;3,-4;8,-5;6,-1;14,2;3,4;4,0;3,2;10,1;3,3;13,0;10,3;9,3;5,1;8,-3;4,-3;9,-1;7,2;3,5;2,-4;8,3;8,0;5,-2;3,-3;-1,-1;3,-5;2,-7;1,-3;4,-8;5,-7;-1,-8;2,-4;-3,-5;4,-4;-6,1;-9,-2;-7,6;-15,1;-8,-5;-11,-1;-2,4;-7,2;-10,-6;-11,0;-6,-10;-7,-5;5,-8;-6,-5;11,-9;15,-1;4,-7;19,1;12,-6;12,-3;17,0;17,7;14,4;12,-2;9,1;12,-5;1,-5;-2,-6;-6,-4;-6,-1;-3,-3;-13,-9;-12,-4;-8,-5;7,-2;8,-8;-5,-4;14,-4;0,-3;-9,2;-8,1;-6,3;-10,1;-8,3;0,6;5,3;10,-1;-2,4;-11,2;-13,5;-6,-2;2,-4;-10,-3;1,-2;10,-4;-3,-2;-16,-2;0,-4;-10,1;-3,6;-8,7;0,3;-5,2;-3,-1;-2,12;-6,4;-3,7;3,6;1,4;9,3;-2,2;-12,1;-4,3;-8,5;-4,-4;1,-2;-7,-1;-5,0;-12,2;7,6;-5,1;-6,0;-5,-5;-2,2;3,6;5,5;-4,2;5,5;5,3;0,5;-9,-2;3,5;-6,1;4,9;-7,0;-8,-4;-4,-8;-2,-7;-4,-5;-5,-5;0,-3;-2,-1;0,-2;-6,-4;-1,-4;1,-7;1,-3;-1,-2;-2,-1;-3,-3;-5,-2;-9,-3;-6,-4;-9,-3;-8,-7;2,-1;-5,-4;0,-4;-6,-1;-3,4;-3,-3;0,-4;2,-1;-8,-1;-8,3;1,5;-1,3;3,5;9,5;5,8;11,8;8,0;3,3;-3,2;9,3;7,3;9,5;1,2;-2,4;-6,-5;-8,-1;-4,6;7,4;-1,5;-5,1;-5,8;-4,1;0,-3;2,-6;2,-2;-4,-5;-3,-5;-4,-2;-3,-4;-6,-2;-5,-4;-7,-1;-8,-4;-9,-7;-7,-5;-3,-10;-5,-1;-8,-4;-5,2;-6,4;-4,1;-9,6;-19,-3;-15,3;-1,6;0,6;-9,7;-13,2;-1,3;-6,6;-4,8;4,6;-6,4;-2,7;-7,2;-7,7;-13,0;-10,0;-6,4;-4,4;-5,-1;-3,-4;-3,-5;-10,-2;-4,3;-5,-2;-5,1;2,-8;-1,-6;-5,-1;-2,-3;1,-7;4,-4;0,-4;2,-6;0,-4;-2,-3;0,-4;0,-7;-4,-4;14,-7;12,1;14,0;11,2;8,-1;16,1;5,-6;2,-20;-10,-11;-8,-5;-15,-4;-1,-7;13,-2;17,3;-3,-12;9,5;23,-8;3,-8;9,-2;8,-2;5,-3;9,-15;14,-4;8,0;2,-2;8,0;2,2;7,-5;-2,-4;-1,-6;-4,-5;0,-10;2,-3;2,-3;9,-1;4,-2;8,-3;-1,5;-2,3;1,3;5,1;-2,4;-3,-1;-8,7;3,5;0,4;10,2;0,4;11,-2;5,-3;11,4;5,3;7,-3;16,-4;12,-4;10,2;1,3;10,0;2,-5;14,-3;-2,-8;0,-8;5,-6;9,-4;8,8;8,0;2,-8;1,-6;-3,1;-7,-3;-1,-6;13,-3;13,-1;10,2;11,-1;11,-5;-10,-5;-18,1;-18,3;-16,3;-6,-6;-10,-3;2,-10;-4,-9;4,-6;9,-6;23,-11;7,-2;-1,-4;-14,-5;-17,3;-10,7;2,6;-16,8;-20,9;-7,14;7,7;10,5;-9,11;-11,3;-4,17;-5,9;-12,-1;-6,8;-12,0;-3,-9;-8,-11;-8,-15;-6,-6;-20,12;-13,2;-14,-5;-4,-11;-3,-23;9,-6;27,-9;19,-10;19,-14;24,-19;16,-8;28,-12;22,-5;16,1;15,-8;19,0;18,-2;31,7;-13,3;11,6;10,-3;17,6;27,2;38,12;8,4;0,7;-11,5;-16,3;-45,-8;-7,2;16,7;1,15;13,3;8,2;1,-4;-6,-5;7,-3;24,6;8,-3;-6,-7;23,-10;9,1;10,3;5,-7;-8,-6;5,-6;-7,-6;28,4;5,5;-12,1;0,6;7,3;16,-2;2,-6;21,-5;35,-9;8,1;-10,6;12,1;7,-3;19,-1;15,-4;11,6;12,-6;-11,-6;6,-4;29,4;14,3;36,11;7,-5;-10,-5;-1,-3;-12,-1;4,-4;-6,-8;0,-3;18,-9;7,-9;7,-2;27,2;2,6;-10,8;7,3;3,7;-2,14;11,6;-5,7;-19,14;11,1;4,-3;11,-3;3,-5;9,-5;-6,-5;4,-7;-11,-1;-2,-5;8,-10;-13,-8;18,-7;-2,-7;5,-1;5,6;-4,10;11,1;-5,-7;17,-4;21,0;18,6;-9,-9;-1,-10;18,-3;24,1;21,-1;-8,-6;12,-6;11,0;20,-5;26,-2;3,-2;27,-1;8,2;22,-5;19,0;2,-5;10,-4;24,-4;17,3;-14,3;23,1;2,5;10,-2;29,0;22,5;8,4;-2,5;-11,3;-26,5;-8,3;12,2;15,2;9,-2;5,7;5,-3;16,-2;32,2;2,5;42,1;1,-7;21,1;16,0;16,6;5,6;-6,4;12,8;16,4;10,-10;16,4;17,-3;19,4;7,-3;17,1;-8,-9;14,-4;90,6;9,6;26,8;40,-2;20,1;8,4;-1,8;12,3;14,-2;18,-1;18,2;19,-1;18,9;12,-3;-8,-7;5,-4;31,3;21,-1;29,5;14,4|2291,487;5,7;5,1;3,2;-8,1;-2,8;-2,4;-3,2;0,5;3,7;9,2;7,5;15,2;15,-3;1,-2;-2,-7;2,-11;-8,-3;3,-7;-7,0;2,-9;10,3;8,-4;-7,-6;-3,-5;-8,2;-1,8;-3,-7;-1,-2;3,-4;-2,-4;-12,-3;-4,-9;-6,-3;0,-3;10,1;0,-7;9,-2;8,1;2,-9;-2,-7;-10,1;-8,-2;-12,4;-9,2;-5,6;-9,2;-10,10;9,9;-1,7;11,12;5,5|844,209;-7,3;-13,-3;-8,1;-14,-4;9,-3;7,-4;10,2;6,2;3,2;7,4|0,185;0,7;-11,0;-2,-3;13,-4|0,185;1,-1;9,0;14,3;-1,2;-10,2;-13,1;0,-7|895,205;0,10;13,-8;12,7;-3,7;10,7;10,-7;7,-9;1,-11;14,1;15,1;13,5;1,5;-8,6;7,5;-1,5;-19,7;-14,1;-11,-3;-3,5;-9,9;-3,4;-12,7;-14,1;-8,4;-1,6;-11,2;-13,8;-10,11;-4,8;-1,12;15,1;4,10;5,7;14,-2;19,4;10,4;7,5;12,3;11,4;16,1;11,1;-1,8;3,10;7,11;15,10;8,-3;5,-11;-5,-15;-7,-6;16,-4;11,-7;6,-7;-1,-7;-7,-9;-12,-7;12,-11;-5,-9;-3,-15;7,-3;17,3;10,1;9,-2;9,3;12,6;3,4;18,0;0,9;3,12;9,2;7,6;15,-6;10,-11;6,-4;8,9;13,12;11,12;-4,7;13,5;9,6;16,3;7,3;4,8;7,2;4,3;1,12;-7,3;-7,4;-17,3;-12,9;-17,1;-22,-2;-15,0;-10,1;-8,7;-13,4;-15,14;-11,9;8,-2;16,-13;21,-8;15,-1;9,5;-9,6;3,11;3,8;13,5;17,-2;10,-11;0,7;7,4;-12,6;-23,6;-9,4;-12,8;-7,-1;-1,-9;18,-8;-16,0;-11,2;1,3;-10,5;-11,3;-10,3;-6,7;-1,1;0,6;3,5;4,0;-1,-3;3,2;-1,3;-6,1;-5,0;-8,2;-4,0;-6,1;-8,3;15,-2;3,2;-14,3;-7,0;0,-2;-3,3;3,1;-2,7;-7,8;-1,-3;-2,0;-3,-3;2,5;2,2;0,4;-3,4;-5,8;-1,-1;3,-6;-5,-4;-2,-8;-1,4;2,6;-7,-1;7,3;0,9;3,1;1,3;2,10;-7,8;-10,3;-7,6;-5,0;-5,4;-1,3;-11,7;-6,5;-4,6;-2,7;2,7;3,8;5,7;0,5;4,11;0,7;0,4;-3,6;-3,1;-5,-1;-1,-4;-4,-3;-5,-8;-5,-8;-2,-4;2,-7;-2,-5;-8,-8;-4,-2;-10,5;-2,-1;-5,-5;-6,-2;-11,1;-9,-1;-8,1;-4,1;2,3;0,4;2,2;-2,1;-4,-1;-4,2;-7,0;-7,-6;-9,1;-7,-2;-6,1;-9,2;-9,8;-10,4;-5,5;-3,4;0,7;1,5;2,3;-4,9;-2,7;-1,14;-1,5;2,5;3,5;2,8;7,7;2,6;4,5;11,2;4,5;9,-3;7,-1;8,-2;6,-2;6,-4;3,-6;0,-8;2,-3;7,-3;11,-2;8,0;6,0;3,2;0,5;-6,5;-2,7;2,1;-2,5;-2,7;-3,-2;-2,0;0,1;2,1;0,2;-2,5;1,1;-1,4;1,1;-2,5;-2,2;-1,1;-2,3;3,2;1,-2;3,2;1,0;2,-2;3,0;1,1;1,0;5,0;5,0;3,-1;1,-1;3,0;3,1;2,0;2,-1;5,1;1,1;3,2;3,2;4,1;3,3;-1,1;-1,2;1,4;-2,3;-1,4;-1,5;1,2;0,5;-1,1;-1,4;0,3;-2,2;1,3;1,2;3,5;4,4;5,4;3,4;0,2;4,0;1,0;3,2;5,-1;4,-2;6,-2;3,-3;6,0;-1,1;6,1;4,2;4,3;3,2;6,1;7,-7;4,-1;0,-4;2,-8;6,-5;6,0;1,-2;8,1;8,-5;4,-3;4,-4;4,0;3,3;-2,3;-1,3;-5,1;3,4;0,6;-5,5;4,8;4,0;3,-8;-4,-3;0,-8;12,-4;-1,-4;4,-4;3,7;7,1;7,5;0,3;9,1;11,-1;5,4;8,1;6,-3;0,-2;12,-1;12,0;-8,3;3,5;8,0;8,5;1,8;5,0;4,2;7,4;6,7;0,5;4,0;6,5;4,3;12,2;1,-2;8,0;10,2;4,2;7,2;11,8;1,4;4,0;2,6;6,17;5,2;1,7;-8,8;3,3;18,1;0,10;8,-6;12,3;17,7;5,5;-2,6;12,-3;19,5;15,0;15,8;13,11;7,3;9,0;4,4;3,12;2,6;-4,17;-5,6;-14,14;-7,12;-7,8;-3,1;-3,7;1,19;-3,15;-1,7;-3,4;-2,13;-10,13;-1,10;-9,5;-2,6;-11,0;-15,4;-8,4;-11,3;-11,8;-9,10;-1,7;1,6;-2,10;-2,5;-7,5;-11,18;-9,8;-7,4;-4,10;-7,6;-4,6;-11,6;-8,-2;-5,1;-9,-5;-7,1;-6,-6;-1,5;13,9;-2,7;7,4;-1,5;-9,13;-15,5;-20,2;-11,-1;2,6;-2,8;2,5;-6,3;-11,2;-9,-4;-4,3;1,10;7,3;5,-4;3,6;-9,3;-8,6;-1,10;-3,5;-9,0;-8,6;-3,7;10,7;10,2;-4,9;-12,6;-6,12;-9,4;-4,4;3,11;6,6;-4,-1;-9,0;-4,2;-9,4;-2,9;-4,1;-12,-4;-11,-7;-12,-5;-4,-7;3,-6;-5,-6;-1,-17;4,-10;11,-8;-15,-3;9,-8;3,-17;12,4;5,-21;-7,-3;-3,13;-6,-2;3,-14;3,-19;5,-6;-3,-10;-1,-11;4,-1;6,-16;7,-16;5,-15;-3,-15;3,-8;-1,-12;6,-13;2,-19;3,-21;3,-22;-1,-16;-2,-15;-10,-5;-1,-4;-19,-10;-18,-11;-8,-7;-4,-8;1,-3;-8,-13;-10,-18;-9,-20;-4,-5;-4,-7;-7,-7;-8,-4;4,-4;-5,-10;3,-7;8,-6;5,-7;-2,-5;-4,5;-6,-5;2,-2;-1,-9;3,-2;2,-6;4,-7;-1,-4;6,-2;6,-4;-1,-3;4,-1;-1,-5;3,-3;5,-1;4,-6;4,-5;-4,-3;2,-6;-2,-9;2,-2;-2,-9;-4,-5;-3,-3;-2,-6;2,-2;-2,-1;-2,-3;-5,-3;-5,1;-2,3;-4,3;-2,0;-1,2;5,6;-3,1;-1,1;-5,1;-2,-6;-1,2;-3,-1;-2,-4;-4,-1;-3,-1;-4,0;0,2;-2,-1;-5,-2;-2,-3;1,-1;0,-3;-3,-2;-4,-2;-3,-1;-1,-3;-3,-2;1,3;-2,2;-2,-2;-4,-1;-1,-2;0,-3;1,-4;-2,-1;2,-2;-4,-3;-4,-4;-2,-3;-5,-4;-5,-4;1,-2;2,2;1,-1;-2,-3;-3,-1;-1,3;-6,-1;-3,-1;-5,-2;-5,0;-3,-2;-5,-2;-6,0;-5,-2;-5,-4;-12,-11;-5,-3;-8,-3;-6,1;-8,3;-5,1;-7,-2;-7,-2;-9,-5;-8,-1;-11,-5;-9,-4;-2,-3;-6,-1;-10,-3;-4,-4;-11,-6;-5,-6;-2,-5;3,-1;-1,-3;2,-3;0,-3;-3,-5;-1,-4;-3,-5;-9,-10;-10,-7;-5,-7;-9,-4;-1,-2;1,-6;-5,-3;-6,-5;-2,-7;-6,0;-6,-6;-4,-5;-1,-3;-5,-7;-4,-8;1,-4;-8,-4;-3,1;-6,-3;-1,4;1,5;1,7;4,4;7,7;2,3;1,0;2,4;1,0;2,6;3,3;3,3;6,5;3,10;3,4;3,5;0,5;5,0;4,5;4,4;0,2;-5,4;-1,0;-3,-6;-7,-6;-7,-5;-5,-2;0,-8;-1,-5;-5,-3;-7,-5;-1,2;-2,-3;-7,-2;-6,-6;1,-1;4,1;4,-4;0,-5;-7,-7;-6,-3;-4,-6;-4,-6;-4,-8;-4,-9;-2,-5;-6,-6;-5,-1;-1,-3;-6,-1;-3,-2;-10,-1;-2,-2;-1,-6;-10,-10;-8,-14;0,-2;-5,-3;-7,-9;-2,-8;-5,-5;2,-8;0,-9;-3,-8;4,-9;2,-18;-2,-14;-3,-8;-3,-5;1,-2;15,4;5,9;3,-3;-2,-8;-3,-8;-2,0;-19,-10;-7,-4;-18,-4;-6,-9;2,-6;-13,-5;-2,-8;-12,-7;0,-5;-6,-4;-9,-3;-2,-9;-13,-8;-6,-9;-9,-1;-16,0;-12,-3;-21,-10;-9,-2;-18,-4;-14,1;-19,-5;-12,-4;-11,2;2,7;-6,1;-11,2;-9,3;-11,2;-2,-5;5,-10;11,-3;-3,-3;-13,6;-7,6;-14,7;7,5;-9,8;-11,4;-10,3;-3,4;-15,5;-3,5;-12,4;-7,0;-9,2;-10,4;-9,3;-17,3;-1,-2;11,-4;9,-3;11,-6;12,-1;5,-4;14,-6;2,-2;8,-4;1,-7;6,-6;-12,3;-3,-2;-6,4;-6,-5;-3,3;-4,-5;-10,4;-6,0;-1,-6;2,-3;-6,-4;-13,2;-9,-5;-6,-2;-1,-6;-7,-4;4,-6;8,-5;3,-5;8,-1;7,1;8,-4;8,0;7,-3;-2,-4;-5,-2;7,-4;-6,0;-11,2;-3,3;-7,-3;-15,2;-14,-3;-4,-4;-13,-6;14,-4;22,-5;8,0;-1,5;21,0;-8,-6;-12,-4;-7,-5;-10,-4;-14,-4;6,-5;18,0;12,-5;3,-5;10,-4;10,-1;19,-5;9,1;15,-6;15,3;8,4;4,-2;17,1;-1,2;16,2;10,-1;21,3;19,1;8,1;13,-2;15,3;11,2;19,2;16,5;10,1;9,-4;12,-3;15,1;15,-4;16,-3;7,4;7,-2;3,-5;7,1;16,9;14,-7;1,8;12,-2;4,-3;12,1;16,4;23,4;14,2;10,-1;13,5;-14,5;18,2;27,-1;9,-2;10,6;11,-5;-10,-4;6,-4;12,0;9,-1;8,2;10,6;11,-1;17,5;16,-2;15,0;-2,-6;9,-2;16,4;0,9;6,-8;8,0;5,-10;-11,-6;-12,-4;1,-11;12,-7;13,1;10,5;14,11;-9,5;19,2|658,169;-5,4;23,-3;13,5;12,-5;9,4;8,9;5,-4;-7,-10;9,-1;10,1;11,4;6,10;3,7;17,5;18,5;-1,4;-16,1;6,4;-3,3;-18,-1;-18,-3;-11,1;-19,3;-30,2;-13,1;-6,-5;-13,-3;-9,1;-12,-8;6,-1;16,-1;14,0;13,-2;-19,-2;-22,1;-14,0;-5,-4;23,-4;-16,0;-17,-3;8,-7;7,-4;27,-6;10,2|755,166;-9,6;-15,-7;3,-1;13,0;8,2|1037,169;0,3;-10,-1;-11,0;-11,2;-3,-1;-11,-5;1,-4;4,-1;23,1;18,6|934,168;8,7;9,-8;26,-5;17,11;-2,6;20,-3;10,-4;22,6;14,4;1,5;19,-3;10,7;24,4;9,4;9,9;-18,5;23,6;16,3;15,9;15,0;-3,7;-17,12;-12,-4;-16,-10;-13,1;-1,6;10,6;14,5;4,2;6,10;-3,7;-13,-2;-25,-8;14,8;11,6;1,4;-27,-4;-21,-6;-12,-5;3,-3;-15,-5;-14,-5;0,3;-29,2;-9,-4;7,-7;19,0;20,-2;-3,-3;4,-5;12,-10;-2,-4;-4,-4;-15,-5;-21,-3;7,-2;-11,-7;-9,0;-8,-4;-5,3;-18,2;-36,-3;-22,-3;-16,-1;-8,-4;10,-4;-14,0;-3,-10;8,-9;10,-4;26,-3;-8,6|796,162;12,2;18,-2;3,3;-10,5;16,4;-2,9;-17,4;-9,-1;-7,-3;-25,-8;0,-3;21,1;-11,-7;11,-4|3236,168;-15,0;-21,-1;-1,-1;9,-4;13,-1;14,4;1,3|868,172;-11,8;-11,-1;-6,-8;0,-5;5,-5;10,-2;21,0;19,2;-15,9;-12,2|595,186;-26,5;-5,-4;-23,-6;3,-3;8,-8;9,-7;-10,-6;34,-1;14,2;25,0;10,3;11,4;-13,3;-24,7;-13,7;0,4|3307,149;-11,4;-16,-1;-19,-4;3,-3;18,2;25,2|864,150;-6,4;-14,-1;-12,-2;5,-5;14,-2;9,3;4,3|3251,144;-8,8;-37,0;-16,2;-20,-7;5,-6;13,-2;27,0;36,5|815,133;8,4;0,6;-5,7;-16,1;-11,-2;0,-5;-16,0;-1,-7;11,0;15,-3;14,0;1,-1|718,138;4,4;9,-2;10,0;2,5;-6,5;-34,1;-25,5;-15,0;-2,-3;21,-5;-45,2;-14,-2;14,-10;9,-3;28,4;18,6;17,0;-14,-9;9,-4;10,1;4,5|2375,193;-6,1;-32,-2;-3,-4;-18,-3;-1,-5;10,-2;-1,-6;20,-8;-9,-2;24,-8;-3,-5;23,-5;33,-7;33,-1;17,-4;20,-1;7,4;-7,3;-36,5;-30,4;-31,10;-15,10;-16,9;2,9;19,8|853,129;11,3;20,0;9,3;-3,4;12,3;6,2;14,0;14,1;16,-2;20,-1;17,1;10,4;3,4;-7,2;-14,3;-13,-2;-29,2;-20,0;-17,-1;-26,-3;-4,-6;-1,-5;-10,-4;-21,-1;-11,-4;4,-4;20,1|638,124;-1,7;-8,4;-9,0;-19,4;-16,2;-14,-2;17,-8;21,-6;15,0;14,-1|862,125;-5,0;-19,-1;-2,-2;20,0;7,2;-1,1|698,123;-19,3;-14,-3;8,-4;14,-1;14,2;-3,3|2047,121;-22,5;-18,-3;7,-2;-6,-4;21,-2;4,4;14,2|703,114;-12,2;-16,0;0,-2;10,-3;5,1;13,2|842,119;-15,3;-8,-3;-5,-4;0,-4;13,1;5,0;12,4;-2,3|799,117;4,4;-16,-1;-16,-3;-23,-1;10,-3;-12,-2;-1,-4;20,1;27,4;7,5|2851,117;-57,4;19,-13;8,-1;7,0;26,6;-3,4|1983,103;32,7;-25,4;-5,8;-9,2;-5,8;-12,0;-21,-6;9,-3;-15,-3;-20,-9;-8,-8;28,-3;5,3;14,0;4,-3;15,-1;13,4|2054,96;20,3;-15,6;-29,1;-29,-2;-2,-2;-14,-1;-11,-4;31,-3;14,2;10,-3;25,3|2311,95;-13,1;-9,1;-1,1;-12,2;-11,-2;6,-4;-23,0;20,-2;15,0;2,3;6,-3;9,-1;15,2;-4,2|2799,111;-21,1;-28,-2;-17,-4;-8,-7;-13,-2;26,-7;21,-3;20,6;23,9;-3,9|930,103;12,4;-14,3;-18,7;-18,1;-21,-1;-11,-5;1,-3;8,-3;-19,0;-11,-3;-6,-5;7,-4;7,-3;10,-1;-4,-2;23,-1;13,6;17,2;16,2;8,6|1115,69;27,1;21,1;18,3;0,2;-24,5;-25,2;-9,2;22,0;-23,6;-17,3;-17,8;-20,2;-7,2;-30,1;14,1;-7,2;8,5;-9,3;-16,3;-5,4;-14,3;2,2;17,0;0,2;-27,6;-26,-3;-29,2;-15,-1;-19,-1;-1,-5;18,-2;-5,-7;7,-1;26,5;-13,-7;-17,-2;8,-4;18,-2;3,-3;-14,-4;-4,-6;27,1;8,1;16,-4;-23,-1;-35,1;-18,-4;-8,-4;-12,-3;-2,-3;15,-2;12,0;19,-2;15,-4;12,1;11,3;8,-6;13,-1;18,-1;30,-1;6,1;29,-1;21,0;22,1|1529,65;63,8;-19,4;-38,0;-54,1;5,2;35,-1;31,3;19,-3;8,4;-11,5;26,-3;48,-4;30,2;6,4;-41,7;-5,3;-32,1;23,1;-12,7;-8,6;0,12;12,6;-15,1;-17,3;19,5;2,9;-11,0;13,9;-22,1;12,4;-4,3;-14,2;-14,0;13,7;0,4;-20,-4;-5,3;14,2;13,6;3,8;-17,2;-8,-4;-12,-5;3,6;-12,6;27,0;14,1;-27,8;-27,8;-30,4;-11,0;-10,4;-14,10;-22,7;-6,1;-14,2;-14,2;-9,7;0,7;-5,6;-16,8;4,8;-5,8;-5,10;-14,1;-15,-9;-20,0;-9,-5;-7,-10;-17,-12;-5,-7;-2,-9;-14,-9;4,-7;-7,-4;10,-12;15,-3;4,-4;2,-8;-11,3;-6,2;-9,1;-12,-3;-1,-7;4,-5;10,0;20,2;-17,-6;-9,-3;-10,1;-8,-3;11,-9;-6,-4;-8,-7;-12,-10;-13,-4;0,-4;-27,-6;-21,-1;-27,1;-24,0;-12,-3;-17,-6;26,-3;20,-1;-42,-2;-23,-4;1,-4;38,-5;37,-5;4,-4;-27,-3;9,-4;34,-7;15,-1;-4,-5;23,-2;31,-2;31,0;11,3;26,-5;24,3;14,1;21,3;-24,-5;1,-4;34,-6;35,0;13,-3;35,-1;80,1";
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// A small generated picture (sky, sun, two hills) as a PNG data URI, so the Image sample needs no file.
|
|
2
|
+
import { deflateSync } from "node:zlib";
|
|
3
|
+
|
|
4
|
+
const crcTable = (() => {
|
|
5
|
+
const t = new Uint32Array(256);
|
|
6
|
+
for (let n = 0; n < 256; n++) {
|
|
7
|
+
let c = n;
|
|
8
|
+
for (let k = 0; k < 8; k++) c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1;
|
|
9
|
+
t[n] = c >>> 0;
|
|
10
|
+
}
|
|
11
|
+
return t;
|
|
12
|
+
})();
|
|
13
|
+
const crc32 = (buf: Uint8Array): number => {
|
|
14
|
+
let c = 0xffffffff;
|
|
15
|
+
for (let i = 0; i < buf.length; i++) c = crcTable[(c ^ buf[i]) & 0xff] ^ (c >>> 8);
|
|
16
|
+
return (c ^ 0xffffffff) >>> 0;
|
|
17
|
+
};
|
|
18
|
+
const chunk = (type: string, data: Uint8Array): Buffer => {
|
|
19
|
+
const out = Buffer.alloc(12 + data.length);
|
|
20
|
+
out.writeUInt32BE(data.length, 0);
|
|
21
|
+
out.write(type, 4, "ascii");
|
|
22
|
+
Buffer.from(data).copy(out, 8);
|
|
23
|
+
out.writeUInt32BE(crc32(out.subarray(4, 8 + data.length)), 8 + data.length);
|
|
24
|
+
return out;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/** An RGB PNG from a per-pixel function. */
|
|
28
|
+
export function encodePng(w: number, h: number, pixel: (x: number, y: number) => [number, number, number]): Buffer {
|
|
29
|
+
const raw = Buffer.alloc((w * 3 + 1) * h);
|
|
30
|
+
for (let y = 0; y < h; y++) {
|
|
31
|
+
raw[y * (w * 3 + 1)] = 0;
|
|
32
|
+
for (let x = 0; x < w; x++) {
|
|
33
|
+
const [r, g, b] = pixel(x, y);
|
|
34
|
+
const o = y * (w * 3 + 1) + 1 + x * 3;
|
|
35
|
+
raw[o] = r;
|
|
36
|
+
raw[o + 1] = g;
|
|
37
|
+
raw[o + 2] = b;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const ihdr = Buffer.alloc(13);
|
|
41
|
+
ihdr.writeUInt32BE(w, 0);
|
|
42
|
+
ihdr.writeUInt32BE(h, 4);
|
|
43
|
+
ihdr[8] = 8; // bit depth
|
|
44
|
+
ihdr[9] = 2; // truecolor
|
|
45
|
+
return Buffer.concat([Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]), chunk("IHDR", ihdr), chunk("IDAT", deflateSync(raw)), chunk("IEND", new Uint8Array(0))]);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const mix = (a: number[], b: number[], t: number): [number, number, number] => [a[0] + (b[0] - a[0]) * t, a[1] + (b[1] - a[1]) * t, a[2] + (b[2] - a[2]) * t];
|
|
49
|
+
|
|
50
|
+
export function samplePng(w = 192, h = 108): Buffer {
|
|
51
|
+
return encodePng(w, h, (x, y) => {
|
|
52
|
+
const v = y / h;
|
|
53
|
+
let c: [number, number, number] = mix([18, 24, 66], [255, 150, 70], Math.min(1, v * 1.35));
|
|
54
|
+
const sx = w * 0.68;
|
|
55
|
+
const sy = h * 0.5;
|
|
56
|
+
const d = Math.hypot(x - sx, (y - sy) * 1.0);
|
|
57
|
+
if (d < h * 0.17) c = mix([255, 244, 200], [255, 190, 90], d / (h * 0.17));
|
|
58
|
+
else if (d < h * 0.3) c = mix(c, [255, 200, 120], 0.35 * (1 - (d - h * 0.17) / (h * 0.13)));
|
|
59
|
+
const far = h * (0.66 + 0.07 * Math.sin(x / 17) + 0.04 * Math.sin(x / 6));
|
|
60
|
+
const near = h * (0.8 + 0.06 * Math.sin(x / 11 + 2) + 0.03 * Math.sin(x / 4));
|
|
61
|
+
if (y > far) c = mix([40, 60, 90], [20, 36, 62], (y - far) / (h - far));
|
|
62
|
+
if (y > near) c = mix([14, 30, 38], [6, 14, 22], (y - near) / (h - near));
|
|
63
|
+
return [Math.round(c[0]), Math.round(c[1]), Math.round(c[2])];
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export const SAMPLE_PNG_DATA_URI = `data:image/png;base64,${samplePng().toString("base64")}`;
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
// Text measurement and a cell canvas. Pure, no dependencies.
|
|
2
|
+
|
|
3
|
+
const seg: { segment(s: string): Iterable<{ segment: string }> } | null =
|
|
4
|
+
typeof Intl !== "undefined" && (Intl as any).Segmenter ? new (Intl as any).Segmenter(undefined, { granularity: "grapheme" }) : null;
|
|
5
|
+
|
|
6
|
+
export function graphemes(s: string): string[] {
|
|
7
|
+
return seg ? Array.from(seg.segment(s), (x) => x.segment) : Array.from(s);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function cpWidth(cp: number): number {
|
|
11
|
+
if (cp === 0 || cp < 32 || (cp >= 0x7f && cp < 0xa0)) return 0;
|
|
12
|
+
if ((cp >= 0x300 && cp <= 0x36f) || (cp >= 0x200b && cp <= 0x200f) || (cp >= 0xfe00 && cp <= 0xfe0f) || (cp >= 0x20d0 && cp <= 0x20ff)) return 0;
|
|
13
|
+
if (
|
|
14
|
+
(cp >= 0x1100 && cp <= 0x115f) ||
|
|
15
|
+
(cp >= 0x2e80 && cp <= 0xa4cf) ||
|
|
16
|
+
(cp >= 0xac00 && cp <= 0xd7a3) ||
|
|
17
|
+
(cp >= 0xf900 && cp <= 0xfaff) ||
|
|
18
|
+
(cp >= 0xfe30 && cp <= 0xfe6f) ||
|
|
19
|
+
(cp >= 0xff00 && cp <= 0xff60) ||
|
|
20
|
+
(cp >= 0xffe0 && cp <= 0xffe6) ||
|
|
21
|
+
(cp >= 0x1f300 && cp <= 0x1f64f) ||
|
|
22
|
+
(cp >= 0x1f900 && cp <= 0x1f9ff) ||
|
|
23
|
+
(cp >= 0x20000 && cp <= 0x3fffd)
|
|
24
|
+
)
|
|
25
|
+
return 2;
|
|
26
|
+
return 1;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** Display width of one grapheme cluster (0, 1 or 2 columns). */
|
|
30
|
+
export function gWidth(g: string): number {
|
|
31
|
+
let w = 0;
|
|
32
|
+
let sawVs16 = false;
|
|
33
|
+
for (const ch of g) {
|
|
34
|
+
const cp = ch.codePointAt(0)!;
|
|
35
|
+
if (cp === 0xfe0f) sawVs16 = true;
|
|
36
|
+
w = Math.max(w, cpWidth(cp));
|
|
37
|
+
}
|
|
38
|
+
return sawVs16 ? 2 : w;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function textWidth(s: string): number {
|
|
42
|
+
let w = 0;
|
|
43
|
+
for (const g of graphemes(s)) w += gWidth(g);
|
|
44
|
+
return w;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** Cut `s` to at most `max` columns, ending in an ellipsis when something was cut. */
|
|
48
|
+
export function truncateText(s: string, max: number, ell = "…"): string {
|
|
49
|
+
if (max <= 0) return "";
|
|
50
|
+
if (textWidth(s) <= max) return s;
|
|
51
|
+
const ew = textWidth(ell);
|
|
52
|
+
if (max <= ew) return graphemes(ell).slice(0, max).join("");
|
|
53
|
+
let out = "";
|
|
54
|
+
let w = 0;
|
|
55
|
+
for (const g of graphemes(s)) {
|
|
56
|
+
const gw = gWidth(g);
|
|
57
|
+
if (w + gw > max - ew) break;
|
|
58
|
+
out += g;
|
|
59
|
+
w += gw;
|
|
60
|
+
}
|
|
61
|
+
return out + ell;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** Replace control characters and newlines so a label is always one line. */
|
|
65
|
+
export function oneLine(s: string): string {
|
|
66
|
+
return String(s ?? "").replace(/[\u0000-\u001f\u007f]+/g, " ").replace(/\s+/g, " ").trim();
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export interface Cell {
|
|
70
|
+
readonly ch: string; // "" marks the second column of a wide character
|
|
71
|
+
readonly role: string;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Cells are interned and frozen. A widget is mostly blanks and box lines, and one object per terminal cell cost 160 KB per
|
|
76
|
+
* widget (300 widgets in a transcript held 47 MB); shared cells cost a pointer each. Nothing may change a cell: build a new
|
|
77
|
+
* one with `cell()` instead. Freezing makes a mistake throw at once instead of restyling every widget that shares the cell.
|
|
78
|
+
*/
|
|
79
|
+
const pool = new Map<string, Map<string, Cell>>();
|
|
80
|
+
let pooled = 0;
|
|
81
|
+
const POOL_MAX = 50_000;
|
|
82
|
+
export function cell(ch: string, role = ""): Cell {
|
|
83
|
+
let byCh = pool.get(role);
|
|
84
|
+
if (!byCh) pool.set(role, (byCh = new Map()));
|
|
85
|
+
let c = byCh.get(ch);
|
|
86
|
+
if (!c) {
|
|
87
|
+
c = Object.freeze({ ch, role });
|
|
88
|
+
if (pooled < POOL_MAX) {
|
|
89
|
+
byCh.set(ch, c);
|
|
90
|
+
pooled++;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return c;
|
|
94
|
+
}
|
|
95
|
+
export const EMPTY: Cell = cell(" ");
|
|
96
|
+
|
|
97
|
+
export class Canvas {
|
|
98
|
+
readonly w: number;
|
|
99
|
+
readonly h: number;
|
|
100
|
+
readonly ch: string[];
|
|
101
|
+
readonly role: string[];
|
|
102
|
+
constructor(w: number, h: number) {
|
|
103
|
+
this.w = w;
|
|
104
|
+
this.h = h;
|
|
105
|
+
this.ch = new Array(w * h).fill(" ");
|
|
106
|
+
this.role = new Array(w * h).fill("");
|
|
107
|
+
}
|
|
108
|
+
inb(x: number, y: number): boolean {
|
|
109
|
+
return x >= 0 && y >= 0 && x < this.w && y < this.h;
|
|
110
|
+
}
|
|
111
|
+
set(x: number, y: number, ch: string, role = ""): void {
|
|
112
|
+
if (!this.inb(x, y)) return;
|
|
113
|
+
this.ch[y * this.w + x] = ch;
|
|
114
|
+
this.role[y * this.w + x] = role;
|
|
115
|
+
}
|
|
116
|
+
getCh(x: number, y: number): string {
|
|
117
|
+
return this.inb(x, y) ? this.ch[y * this.w + x] : " ";
|
|
118
|
+
}
|
|
119
|
+
getRole(x: number, y: number): string {
|
|
120
|
+
return this.inb(x, y) ? this.role[y * this.w + x] : "";
|
|
121
|
+
}
|
|
122
|
+
isBlank(x: number, y: number): boolean {
|
|
123
|
+
return this.inb(x, y) && this.ch[y * this.w + x] === " " && this.role[y * this.w + x] === "";
|
|
124
|
+
}
|
|
125
|
+
/** Write text starting at (x, y). Returns the number of columns written. */
|
|
126
|
+
text(x: number, y: number, s: string, role = ""): number {
|
|
127
|
+
let cx = x;
|
|
128
|
+
for (const g of graphemes(s)) {
|
|
129
|
+
const gw = gWidth(g);
|
|
130
|
+
if (gw === 0) continue;
|
|
131
|
+
this.set(cx, y, g, role);
|
|
132
|
+
if (gw === 2) this.set(cx + 1, y, "", role);
|
|
133
|
+
cx += gw;
|
|
134
|
+
}
|
|
135
|
+
return cx - x;
|
|
136
|
+
}
|
|
137
|
+
rows(): Cell[][] {
|
|
138
|
+
const out: Cell[][] = [];
|
|
139
|
+
for (let y = 0; y < this.h; y++) {
|
|
140
|
+
const row: Cell[] = [];
|
|
141
|
+
for (let x = 0; x < this.w; x++) row.push(cell(this.ch[y * this.w + x], this.role[y * this.w + x]));
|
|
142
|
+
out.push(row);
|
|
143
|
+
}
|
|
144
|
+
return out;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export interface Rect {
|
|
149
|
+
x: number;
|
|
150
|
+
y: number;
|
|
151
|
+
w: number;
|
|
152
|
+
h: number;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export type Palette = (role: string) => ((s: string) => string) | undefined;
|
|
156
|
+
|
|
157
|
+
/** Turn cell rows into strings, grouping runs of the same role so escapes stay short. */
|
|
158
|
+
export function rowsToLines(rows: Cell[][], palette?: Palette, trim = true): string[] {
|
|
159
|
+
return rows.map((full) => {
|
|
160
|
+
let end = full.length;
|
|
161
|
+
while (trim && end > 0 && full[end - 1].ch === " " && full[end - 1].role === "") end--;
|
|
162
|
+
const row = full.slice(0, end);
|
|
163
|
+
let out = "";
|
|
164
|
+
let runRole: string | null = null;
|
|
165
|
+
let run = "";
|
|
166
|
+
const flush = () => {
|
|
167
|
+
if (runRole === null) return;
|
|
168
|
+
const f = palette ? palette(runRole) : undefined;
|
|
169
|
+
out += f ? f(run) : run;
|
|
170
|
+
run = "";
|
|
171
|
+
};
|
|
172
|
+
for (const c of row) {
|
|
173
|
+
if (c.role !== runRole) {
|
|
174
|
+
flush();
|
|
175
|
+
runRole = c.role;
|
|
176
|
+
}
|
|
177
|
+
run += c.ch;
|
|
178
|
+
}
|
|
179
|
+
flush();
|
|
180
|
+
return out;
|
|
181
|
+
});
|
|
182
|
+
}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
// Dag(nodes, edges, direction?) -> DiagramResult. Never throws on bad input.
|
|
2
|
+
|
|
3
|
+
import { Canvas, oneLine, textWidth, truncateText, type Rect } from "./canvas.ts";
|
|
4
|
+
import { layeredDiagram, type DiagramResult, type LEdgeSpec, type LNodeSpec } from "./layeredDiagram.ts";
|
|
5
|
+
import { budgeted } from "./router.ts";
|
|
6
|
+
|
|
7
|
+
export const DAG_STATUSES = ["done", "running", "failed", "pending", "skipped"] as const;
|
|
8
|
+
export type DagStatus = (typeof DAG_STATUSES)[number];
|
|
9
|
+
|
|
10
|
+
export const STATUS_ICON: Record<string, string> = { done: "✓", running: "◔", failed: "✗", pending: "○", skipped: "⊘" };
|
|
11
|
+
|
|
12
|
+
export interface DagNodeIn {
|
|
13
|
+
id: string;
|
|
14
|
+
label?: string;
|
|
15
|
+
status?: string | null;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface DagOptions {
|
|
19
|
+
direction?: "LR" | "TB" | null;
|
|
20
|
+
/** columns available, default 100 */
|
|
21
|
+
maxWidth?: number;
|
|
22
|
+
/** longest label before truncation, default 28 */
|
|
23
|
+
maxLabel?: number;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
interface Norm {
|
|
27
|
+
nodes: Array<{ id: string; label: string; status: DagStatus | null }>;
|
|
28
|
+
edges: Array<{ a: number; b: number }>;
|
|
29
|
+
warnings: string[];
|
|
30
|
+
selfLoops: Set<number>;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function normalizeDag(nodesIn: unknown, edgesIn: unknown): Norm {
|
|
34
|
+
const warnings: string[] = [];
|
|
35
|
+
const nodes: Norm["nodes"] = [];
|
|
36
|
+
const ids = new Map<string, number>();
|
|
37
|
+
for (const raw of Array.isArray(nodesIn) ? nodesIn : []) {
|
|
38
|
+
const r = (raw ?? {}) as DagNodeIn;
|
|
39
|
+
const id = typeof r.id === "string" ? r.id : r.id == null ? "" : String(r.id);
|
|
40
|
+
if (!id) {
|
|
41
|
+
warnings.push("a node without an id was skipped");
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
if (ids.has(id)) {
|
|
45
|
+
warnings.push(`duplicate node id "${id}" ignored`);
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
let status: DagStatus | null = null;
|
|
49
|
+
if (r.status != null && r.status !== "") {
|
|
50
|
+
if ((DAG_STATUSES as readonly string[]).includes(String(r.status))) status = r.status as DagStatus;
|
|
51
|
+
else warnings.push(`unknown status "${r.status}" on "${id}" ignored`);
|
|
52
|
+
}
|
|
53
|
+
ids.set(id, nodes.length);
|
|
54
|
+
nodes.push({ id, label: oneLine(r.label ?? id) || id, status });
|
|
55
|
+
}
|
|
56
|
+
const edges: Norm["edges"] = [];
|
|
57
|
+
const seen = new Set<string>();
|
|
58
|
+
const selfLoops = new Set<number>();
|
|
59
|
+
for (const raw of Array.isArray(edgesIn) ? edgesIn : []) {
|
|
60
|
+
if (!Array.isArray(raw) || raw.length < 2) {
|
|
61
|
+
warnings.push("an edge that is not a [from, to] pair was skipped");
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
const a = ids.get(String(raw[0]));
|
|
65
|
+
const b = ids.get(String(raw[1]));
|
|
66
|
+
if (a === undefined || b === undefined) {
|
|
67
|
+
warnings.push(`edge ${String(raw[0])} -> ${String(raw[1])} names an unknown node and was skipped`);
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
if (a === b) {
|
|
71
|
+
selfLoops.add(a);
|
|
72
|
+
warnings.push(`self loop on "${nodes[a].id}" shown as a marker`);
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
const key = `${a}>${b}`;
|
|
76
|
+
if (seen.has(key)) continue;
|
|
77
|
+
seen.add(key);
|
|
78
|
+
edges.push({ a, b });
|
|
79
|
+
}
|
|
80
|
+
return { nodes, edges, warnings, selfLoops };
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function paintBox(c: Canvas, r: Rect, role: string, dashed: boolean): void {
|
|
84
|
+
const hz = dashed ? "╌" : "─";
|
|
85
|
+
const vt = dashed ? "╎" : "│";
|
|
86
|
+
c.set(r.x, r.y, "╭", role);
|
|
87
|
+
c.set(r.x + r.w - 1, r.y, "╮", role);
|
|
88
|
+
c.set(r.x, r.y + r.h - 1, "╰", role);
|
|
89
|
+
c.set(r.x + r.w - 1, r.y + r.h - 1, "╯", role);
|
|
90
|
+
for (let x = r.x + 1; x < r.x + r.w - 1; x++) {
|
|
91
|
+
c.set(x, r.y, hz, role);
|
|
92
|
+
c.set(x, r.y + r.h - 1, hz, role);
|
|
93
|
+
}
|
|
94
|
+
for (let y = r.y + 1; y < r.y + r.h - 1; y++) {
|
|
95
|
+
c.set(r.x, y, vt, role);
|
|
96
|
+
c.set(r.x + r.w - 1, y, vt, role);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function nodeSpec(n: Norm["nodes"][number], cap: number, loop: boolean): LNodeSpec {
|
|
101
|
+
const label = truncateText(n.label, cap);
|
|
102
|
+
const icon = n.status ? STATUS_ICON[n.status] : "";
|
|
103
|
+
const shown = (loop ? "∞ " : "") + label;
|
|
104
|
+
const cw = (icon ? 2 : 0) + textWidth(shown);
|
|
105
|
+
return {
|
|
106
|
+
id: n.id,
|
|
107
|
+
label: n.label,
|
|
108
|
+
status: n.status,
|
|
109
|
+
baseW: cw + 4,
|
|
110
|
+
baseH: 3,
|
|
111
|
+
paint: (c, r) => {
|
|
112
|
+
const role = n.status ? `box.${n.status}` : "box";
|
|
113
|
+
paintBox(c, r, role, n.status === "skipped");
|
|
114
|
+
const y = r.y + Math.floor(r.h / 2);
|
|
115
|
+
const x = r.x + 1 + Math.floor((r.w - 2 - cw) / 2);
|
|
116
|
+
let cx = x;
|
|
117
|
+
if (icon) {
|
|
118
|
+
c.set(cx, y, icon, `icon.${n.status}`);
|
|
119
|
+
cx += 2;
|
|
120
|
+
}
|
|
121
|
+
c.text(cx, y, shown, "label");
|
|
122
|
+
},
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function attempt(norm: Norm, dir: "LR" | "TB", cap: number): DiagramResult {
|
|
127
|
+
const nodes = norm.nodes.map((n, i) => nodeSpec(n, cap, norm.selfLoops.has(i)));
|
|
128
|
+
const edges: LEdgeSpec[] = norm.edges.map((e) => ({ a: e.a, b: e.b, fromMark: "none", toMark: "arrow" }));
|
|
129
|
+
return layeredDiagram("dag", { nodes, edges, dashReversed: true }, dir);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const CAPS = [28, 20, 14, 10, 8, 6];
|
|
133
|
+
|
|
134
|
+
export function dag(nodesIn: unknown, edgesIn: unknown, opts: DagOptions = {}): DiagramResult {
|
|
135
|
+
return budgeted(() => dagLayout(nodesIn, edgesIn, opts));
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function dagLayout(nodesIn: unknown, edgesIn: unknown, opts: DagOptions): DiagramResult {
|
|
139
|
+
const norm = normalizeDag(nodesIn, edgesIn);
|
|
140
|
+
const maxWidth = Math.max(20, opts.maxWidth ?? 100);
|
|
141
|
+
const maxLabel = Math.max(6, opts.maxLabel ?? 28);
|
|
142
|
+
if (!norm.nodes.length) {
|
|
143
|
+
return { kind: "dag", direction: "LR", width: 0, height: 0, rows: [], nodes: [], edges: [], warnings: [...norm.warnings, "the graph has no nodes"], footnotes: [], degraded: false, overflow: false, statuses: [], legend: [] };
|
|
144
|
+
}
|
|
145
|
+
const dirs: Array<"LR" | "TB"> = opts.direction === "LR" || opts.direction === "TB" ? [opts.direction] : ["LR", "TB"];
|
|
146
|
+
const longest = Math.max(...norm.nodes.map((n) => textWidth(n.label)));
|
|
147
|
+
let best: DiagramResult | null = null;
|
|
148
|
+
let chosen: DiagramResult | null = null;
|
|
149
|
+
for (const cap of [maxLabel, ...CAPS.filter((c) => c < maxLabel)]) {
|
|
150
|
+
for (const d of dirs) {
|
|
151
|
+
const r = attempt(norm, d, cap);
|
|
152
|
+
if (!best || r.width < best.width) best = r;
|
|
153
|
+
if (r.width <= maxWidth) {
|
|
154
|
+
chosen = r;
|
|
155
|
+
break;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
if (chosen) break;
|
|
159
|
+
if (longest <= cap) break; // shrinking more changes nothing
|
|
160
|
+
}
|
|
161
|
+
if (!chosen) {
|
|
162
|
+
// nothing fits even with short labels: the view will pan anyway, so keep the labels readable
|
|
163
|
+
const cap = Math.min(maxLabel, 14);
|
|
164
|
+
const tries = dirs.map((d) => attempt(norm, d, cap));
|
|
165
|
+
best = tries.reduce((a, b) => (b.width < a.width ? b : a));
|
|
166
|
+
}
|
|
167
|
+
const res = chosen ?? best!;
|
|
168
|
+
res.overflow = !chosen;
|
|
169
|
+
res.warnings = [...norm.warnings];
|
|
170
|
+
if (res.degraded) res.warnings.push("some edges could not be routed cleanly");
|
|
171
|
+
res.statuses = DAG_STATUSES.filter((s) => norm.nodes.some((n) => n.status === s));
|
|
172
|
+
res.legend = res.statuses.map((s) => ({ glyph: STATUS_ICON[s], role: `icon.${s}`, text: s + (s === "skipped" ? " (dashed)" : "") }));
|
|
173
|
+
return res;
|
|
174
|
+
}
|