@storylet-studio/model 0.1.0 → 0.3.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/dist/index.cjs CHANGED
@@ -23,7 +23,10 @@ __export(index_exports, {
23
23
  BOX_SCHEMA: () => BOX_SCHEMA,
24
24
  BUNDLE_EXTENSION: () => BUNDLE_EXTENSION,
25
25
  BUNDLE_SCHEMA: () => BUNDLE_SCHEMA,
26
+ CONTRACTS_DIR: () => CONTRACTS_DIR,
27
+ CONTRACT_SCHEMA: () => CONTRACT_SCHEMA,
26
28
  DECK_SCHEMA: () => DECK_SCHEMA,
29
+ DEFAULT_PLAY_RUNG: () => DEFAULT_PLAY_RUNG,
27
30
  FURNITURE_COLOURS: () => FURNITURE_COLOURS,
28
31
  HANDS_SCHEMA: () => HANDS_SCHEMA,
29
32
  NOTES_SCHEMA: () => NOTES_SCHEMA,
@@ -37,12 +40,15 @@ __export(index_exports, {
37
40
  SPATIAL: () => SPATIAL,
38
41
  TAGS_SCHEMA: () => TAGS_SCHEMA,
39
42
  VIEW_SCHEMA: () => VIEW_SCHEMA,
43
+ ambiguousValueAddressMessage: () => ambiguousValueAddressMessage,
40
44
  backgroundsOf: () => backgroundsOf,
41
45
  bindHand: () => bindHand,
42
46
  bundleAssetPath: () => bundleAssetPath,
43
47
  byDisplayOrder: () => byDisplayOrder,
44
48
  centroid: () => centroid,
45
49
  commentsOf: () => commentsOf,
50
+ contractPropertyPath: () => contractPropertyPath,
51
+ contractPropertyType: () => contractPropertyType,
46
52
  droppedRect: () => droppedRect,
47
53
  effectiveGameId: () => effectiveGameId,
48
54
  framesOf: () => framesOf,
@@ -52,6 +58,7 @@ __export(index_exports, {
52
58
  handBinding: () => handBinding,
53
59
  inferDeclFromWrite: () => inferDeclFromWrite,
54
60
  isCaseOnlyPropertyName: () => import_expr.isCaseOnlyPropertyName,
61
+ isHoleRef: () => isHoleRef,
55
62
  isSpatial: () => isSpatial,
56
63
  isValidGameId: () => isValidGameId,
57
64
  isValidPropertyName: () => import_expr.isValidPropertyName,
@@ -59,6 +66,7 @@ __export(index_exports, {
59
66
  markOf: () => markOf,
60
67
  marksOn: () => marksOn,
61
68
  openThreadCounts: () => openThreadCounts,
69
+ parseHoleRef: () => parseHoleRef,
62
70
  pointInPolygon: () => pointInPolygon,
63
71
  polygonBounds: () => polygonBounds,
64
72
  polygonOf: () => polygonOf,
@@ -67,7 +75,9 @@ __export(index_exports, {
67
75
  spatialOf: () => spatialOf,
68
76
  stacked: () => stacked,
69
77
  threadsFor: () => threadsFor,
78
+ turnSpan: () => turnSpan,
70
79
  unbindHand: () => unbindHand,
80
+ valueAddresses: () => valueAddresses,
71
81
  withBackgrounds: () => withBackgrounds,
72
82
  withPolygon: () => withPolygon,
73
83
  withSpatialGroup: () => withSpatialGroup,
@@ -467,6 +477,41 @@ function effectiveGameId(entity) {
467
477
  const fromTitle = entity.title ? gameIdify(entity.title) : "";
468
478
  return fromTitle || entity.id;
469
479
  }
480
+ function valueAddresses(bundle) {
481
+ const tags = [];
482
+ for (const box of bundle.boxes) {
483
+ const boxGameId = effectiveGameId(box);
484
+ for (const group of box.tagGroups) {
485
+ for (const tag of group.tags) {
486
+ const gameId = effectiveGameId(tag);
487
+ tags.push({ id: tag.id, gameId, qualified: `${boxGameId}/${gameId}` });
488
+ }
489
+ }
490
+ }
491
+ const forms = /* @__PURE__ */ new Map();
492
+ for (const tag of tags) {
493
+ const list = forms.get(tag.gameId) ?? [];
494
+ if (!list.includes(tag.qualified)) list.push(tag.qualified);
495
+ forms.set(tag.gameId, list);
496
+ }
497
+ const print = /* @__PURE__ */ new Map();
498
+ const accept = /* @__PURE__ */ new Map();
499
+ const repeated = /* @__PURE__ */ new Map();
500
+ for (const tag of tags) {
501
+ const candidates = forms.get(tag.gameId) ?? [tag.qualified];
502
+ const ambiguous = candidates.length > 1;
503
+ print.set(tag.id, ambiguous ? tag.qualified : tag.gameId);
504
+ if (!accept.has(tag.qualified)) accept.set(tag.qualified, tag.id);
505
+ if (!ambiguous && !accept.has(tag.gameId)) accept.set(tag.gameId, tag.id);
506
+ if (ambiguous) repeated.set(tag.gameId, candidates);
507
+ }
508
+ return { print, accept, repeated };
509
+ }
510
+ function ambiguousValueAddressMessage(segment, name, candidates) {
511
+ const forms = candidates.map((q) => `"value.${q}.${name}"`);
512
+ const list = forms.length <= 1 ? forms[0] ?? "" : `${forms.slice(0, -1).join(", ")} or ${forms[forms.length - 1]}`;
513
+ return `"value.${segment}.${name}" names a tag in ${candidates.length} boxes; write ${list}`;
514
+ }
470
515
  function freeGameId(base, taken) {
471
516
  let gameId = base;
472
517
  for (let n = 2; taken.has(gameId); n++) gameId = `${base}-${n}`;
@@ -480,8 +525,32 @@ function freeTitle(base, taken) {
480
525
  for (let n = 2; taken.has(gameIdify(title)); n++) title = `${base} ${n}`;
481
526
  return title;
482
527
  }
528
+ function turnSpan(turns, seconds, long = false) {
529
+ const total = Math.max(0, Math.round(turns * seconds));
530
+ const say = (n, short, one, many) => long ? `${n} ${n === 1 ? one : many}` : `${n} ${short}`;
531
+ if (total < 60) return long ? say(total, "s", "second", "seconds") : `${total}s`;
532
+ if (total < 3600) {
533
+ const minutes = total % 60 === 0 ? total / 60 : Math.round(total / 6) / 10;
534
+ return say(minutes, "min", "minute", "minutes");
535
+ }
536
+ let hours = Math.floor(total / 3600);
537
+ let rest = Math.round(total % 3600 / 60);
538
+ if (rest === 60) {
539
+ hours += 1;
540
+ rest = 0;
541
+ }
542
+ const said = say(hours, "hr", "hour", "hours");
543
+ return rest === 0 ? said : `${said} ${say(rest, "min", "minute", "minutes")}`;
544
+ }
483
545
  var PLACE_GROUP = "place";
546
+ var HOLE_REF = /^@(hand|world|story)\.([a-z][a-z0-9_-]*)$/;
547
+ var isHoleRef = (value) => value.startsWith("@");
548
+ var parseHoleRef = (value) => {
549
+ const m = HOLE_REF.exec(value);
550
+ return m === null ? void 0 : { scope: m[1], name: m[2] };
551
+ };
484
552
  var BUNDLE_SCHEMA = "storylets/bundle@0";
553
+ var DEFAULT_PLAY_RUNG = "solo";
485
554
  var SAVE_SCHEMA = "storylets/save@1";
486
555
  var SAVEFILE_SCHEMA = "storylets/savefile@1";
487
556
  var PROJECT_FOLDER_EXTENSION = ".storylets";
@@ -504,8 +573,16 @@ var SHARD_EXTENSIONS = {
504
573
  * id-keyed (design/annotation.md). Documentation NOTES used to share this
505
574
  * file and were retired: `purpose` already says why a thing exists, and
506
575
  * Patterpad's typed routing has no destination here. */
507
- notes: ".storyletnotes"
576
+ notes: ".storyletnotes",
577
+ /** An installation contract: what a VENUE depends on, one file per
578
+ * installation in `contracts/` at the project root
579
+ * (design/engine-server.md 4.11). Its own shard, and its own folder, for the
580
+ * walkthrough's reason (Reboot 7.5, S4): a different owner, a different
581
+ * change rate, and a merge that must never collide with the author's edits,
582
+ * since the server always wins its own file. */
583
+ contract: ".storyletcontract"
508
584
  };
585
+ var CONTRACTS_DIR = "contracts";
509
586
  var PROJECT_SCHEMA = "storylets/project@0";
510
587
  var BOX_SCHEMA = "storylets/box@0";
511
588
  var TAGS_SCHEMA = "storylets/tags@0";
@@ -513,13 +590,19 @@ var HANDS_SCHEMA = "storylets/hands@0";
513
590
  var DECK_SCHEMA = "storylets/deck@0";
514
591
  var VIEW_SCHEMA = "storylets/view@0";
515
592
  var NOTES_SCHEMA = "storylets/notes@0";
593
+ var CONTRACT_SCHEMA = "storylets/contract@0";
594
+ var contractPropertyPath = (p) => typeof p === "string" ? p : p.path;
595
+ var contractPropertyType = (p) => typeof p === "string" ? void 0 : p.type;
516
596
  var FURNITURE_COLOURS = ["paper", "amber", "sage", "sky", "rose", "slate"];
517
597
  // Annotate the CommonJS export names for ESM import in node:
518
598
  0 && (module.exports = {
519
599
  BOX_SCHEMA,
520
600
  BUNDLE_EXTENSION,
521
601
  BUNDLE_SCHEMA,
602
+ CONTRACTS_DIR,
603
+ CONTRACT_SCHEMA,
522
604
  DECK_SCHEMA,
605
+ DEFAULT_PLAY_RUNG,
523
606
  FURNITURE_COLOURS,
524
607
  HANDS_SCHEMA,
525
608
  NOTES_SCHEMA,
@@ -533,12 +616,15 @@ var FURNITURE_COLOURS = ["paper", "amber", "sage", "sky", "rose", "slate"];
533
616
  SPATIAL,
534
617
  TAGS_SCHEMA,
535
618
  VIEW_SCHEMA,
619
+ ambiguousValueAddressMessage,
536
620
  backgroundsOf,
537
621
  bindHand,
538
622
  bundleAssetPath,
539
623
  byDisplayOrder,
540
624
  centroid,
541
625
  commentsOf,
626
+ contractPropertyPath,
627
+ contractPropertyType,
542
628
  droppedRect,
543
629
  effectiveGameId,
544
630
  framesOf,
@@ -548,6 +634,7 @@ var FURNITURE_COLOURS = ["paper", "amber", "sage", "sky", "rose", "slate"];
548
634
  handBinding,
549
635
  inferDeclFromWrite,
550
636
  isCaseOnlyPropertyName,
637
+ isHoleRef,
551
638
  isSpatial,
552
639
  isValidGameId,
553
640
  isValidPropertyName,
@@ -555,6 +642,7 @@ var FURNITURE_COLOURS = ["paper", "amber", "sage", "sky", "rose", "slate"];
555
642
  markOf,
556
643
  marksOn,
557
644
  openThreadCounts,
645
+ parseHoleRef,
558
646
  pointInPolygon,
559
647
  polygonBounds,
560
648
  polygonOf,
@@ -563,7 +651,9 @@ var FURNITURE_COLOURS = ["paper", "amber", "sage", "sky", "rose", "slate"];
563
651
  spatialOf,
564
652
  stacked,
565
653
  threadsFor,
654
+ turnSpan,
566
655
  unbindHand,
656
+ valueAddresses,
567
657
  withBackgrounds,
568
658
  withPolygon,
569
659
  withSpatialGroup,