aboutsummaryrefslogtreecommitdiffstats
path: root/examples
diff options
context:
space:
mode:
authoreunhhu <[email protected]>2026-09-30 06:44:35 +0100
committereunhhu <[email protected]>2026-09-30 06:44:35 +0100
commitb3c01b3a26a7b5fe60b70739a6fc7b5967e0d9c8 (patch)
treef47d4727d954b8260a5eaa8da30e1d28f0e2f47e /examples
parent7705831ebdf94186d1513f3e1b8d7d5ab8b3a2c0 (diff)
downloadvega-b3c01b3a26a7b5fe60b70739a6fc7b5967e0d9c8.tar.gz
vega-b3c01b3a26a7b5fe60b70739a6fc7b5967e0d9c8.zip
Add a board two nodes share
examples/shared-board.aup is the board grown in Pure's research 105: each node sends a changed card whole to the other (send changed { ..at }) and takes the other's whole when it is the later change (cards[k] = Card { ..remote }), by its time and then by the node's name, so both boards end the same whatever order changes come in. The input the other node sends to is the output's like (message like). A new field goes in the card and the output alone. tests/check.py shared_board runs Alice's and Bob's nodes linked both ways over pure://, sealed, each taking the other as its sender: cards added, moved and given on either agree; Bob cut off, both give one card (Bob first, Alice after) and Bob adds one; joined again, both boards take Alice's and Bob's card.
Diffstat (limited to 'examples')
-rw-r--r--examples/shared-board.aup96
1 files changed, 96 insertions, 0 deletions
diff --git a/examples/shared-board.aup b/examples/shared-board.aup
new file mode 100644
index 0000000..a591c49
--- /dev/null
+++ b/examples/shared-board.aup
@@ -0,0 +1,96 @@
+# A board two nodes share. A change to a card goes whole to the other node
+# (send changed { ..at }), and a card the other node sends is taken whole
+# (cards[k] = Card { ..remote }) when it is the later change: by its time,
+# then by the node's name. So both boards end the same, whatever order the
+# changes come in, and after the nodes were cut apart and joined again.
+#
+# Each node runs it with a key of its own and links to the other, sealed:
+# pure-serve --module shared-board.pmod --store a --key a.key --name a \
+# --link-port 7001 --send changed=pure://127.0.0.1:7002/remote \
+# --seal changed=B_KEY --sender b.changed=B_KEY
+# then tells the app its name: POST /inputs/name {"name": "a"}. Upgraded
+# one node after the other, a node takes the other's changes by field name
+# (Pure docs/design/014-fields-by-name.md): add a field to the card and the
+# output, nowhere else.
+use vega
+
+record Card {
+ title: text
+ who: text # whose card it is
+ lane = 0 # 0 to do, 1 doing, 2 done
+ node: text # the node that changed it last
+ since = 0 # when: milliseconds since 1970
+}
+
+state cards: list of Card by title
+state at: index of cards
+state me: text = "me"
+
+input add = text
+input forward = key ArrowRight
+input back = key ArrowLeft
+input up = key ArrowUp
+input down = key ArrowDown
+input name = message {
+ name: text
+}
+input assign = message {
+ title: text
+ who: text
+}
+output changed = message {
+ title: text
+ who: text
+ lane: u32
+ node: text
+ since: number
+}
+input remote = message like changed
+
+fn lane_name(lane) = if lane == 0 { "to do" } else if lane == 1 { "doing" } else { "done" }
+
+on add {
+ cards.add(Card { title: add, since: now, node: me })
+ at = cards[add]
+ send changed { ..at }
+}
+on forward.down {
+ at.lane = min(at.lane + 1, 2)
+ at.since = now
+ at.node = me
+ send changed { ..at }
+}
+on back.down {
+ at.lane = max(at.lane - 1, 0)
+ at.since = now
+ at.node = me
+ send changed { ..at }
+}
+on up.down { at = at - 1 }
+on down.down { at = at + 1 }
+on name { me = name.name }
+on assign {
+ require cards.has(assign.title)
+ cards[assign.title].who = assign.who
+ cards[assign.title].since = now
+ cards[assign.title].node = me
+ send changed { ..cards[assign.title] }
+}
+on remote {
+ if !cards.has(remote.title) {
+ cards.add(Card { ..remote })
+ } else if (remote.since > cards[remote.title].since ||
+ (remote.since == cards[remote.title].since && remote.node > cards[remote.title].node)) {
+ cards[remote.title] = Card { ..remote }
+ }
+}
+
+view title = "{me}'s board"
+view counts = "{count(c in cards where c.lane == 0)} to do, {count(c in cards where c.lane == 1)} doing, {count(c in cards where c.lane == 2)} done"
+
+view cards_list = each c in cards {
+ label = c.title
+ badge = if c.who == "" { lane_name(c.lane) } else { "{c.who}, {lane_name(c.lane)}" }
+ tone = if c.lane == 2 { vega.muted } else { vega.when(c.lane == 1, vega.accent) }
+}
+view cards_list_focus = at.position