Update
This commit is contained in:
parent
4ea5b79f3f
commit
a0143855f3
|
@ -105,7 +105,7 @@ Syndicate.Actor.createFacet()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var _cachedAssertion1468253137502_0 = (function() { var _ = Syndicate.__; return fromBroker(wsurl, locationRecord(id, email, _, _, _)); })();
|
var _cachedAssertion1468253787297_0 = (function() { var _ = Syndicate.__; return fromBroker(wsurl, locationRecord(id, email, _, _, _)); })();
|
||||||
Syndicate.Actor.createFacet()
|
Syndicate.Actor.createFacet()
|
||||||
.addInitBlock((function() {
|
.addInitBlock((function() {
|
||||||
marker.addListener('click', Syndicate.Dataspace.wrap(function () {
|
marker.addListener('click', Syndicate.Dataspace.wrap(function () {
|
||||||
|
@ -132,6 +132,6 @@ Syndicate.Actor.createFacet()
|
||||||
marker.setMap(null);
|
marker.setMap(null);
|
||||||
if (selectedMarker === marker) selectedMarker = null;
|
if (selectedMarker === marker) selectedMarker = null;
|
||||||
}))
|
}))
|
||||||
.onEvent(true, "retracted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(_cachedAssertion1468253137502_0, 0); }), (function() { var _ = Syndicate.__; return { assertion: _cachedAssertion1468253137502_0, metalevel: 0 }; }), (function() {})).completeBuild(); })).completeBuild(); })();
|
.onEvent(true, "retracted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(_cachedAssertion1468253787297_0, 0); }), (function() { var _ = Syndicate.__; return { assertion: _cachedAssertion1468253787297_0, metalevel: 0 }; }), (function() {})).completeBuild(); })).completeBuild(); })();
|
||||||
});
|
});
|
||||||
}).startStepping();
|
}).startStepping();
|
||||||
|
|
|
@ -54,10 +54,10 @@ function todoListItemView(id) {
|
||||||
(function () {
|
(function () {
|
||||||
Syndicate.Actor.createFacet()
|
Syndicate.Actor.createFacet()
|
||||||
.onEvent(false, "asserted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(todo(id, _, _), 0); }), (function() { var _ = Syndicate.__; return { assertion: todo(id, (Syndicate._$("title")), (Syndicate._$("completed"))), metalevel: 0 }; }), (function(title, completed) {
|
.onEvent(false, "asserted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(todo(id, _, _), 0); }), (function() { var _ = Syndicate.__; return { assertion: todo(id, (Syndicate._$("title")), (Syndicate._$("completed"))), metalevel: 0 }; }), (function(title, completed) {
|
||||||
var _cachedAssertion1468253138670_0 = (function() { var _ = Syndicate.__; return todo(id, title, completed); })();
|
var _cachedAssertion1468253788491_0 = (function() { var _ = Syndicate.__; return todo(id, title, completed); })();
|
||||||
Syndicate.Actor.createFacet()
|
Syndicate.Actor.createFacet()
|
||||||
.onEvent(false, "asserted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(show(completed), 0); }), (function() { var _ = Syndicate.__; return { assertion: show(completed), metalevel: 0 }; }), (function() {
|
.onEvent(false, "asserted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(show(completed), 0); }), (function() { var _ = Syndicate.__; return { assertion: show(completed), metalevel: 0 }; }), (function() {
|
||||||
var _cachedAssertion1468253138670_1 = (function() { var _ = Syndicate.__; return show(completed); })();
|
var _cachedAssertion1468253788491_1 = (function() { var _ = Syndicate.__; return show(completed); })();
|
||||||
Syndicate.Actor.createFacet()
|
Syndicate.Actor.createFacet()
|
||||||
.addAssertion((function() { var _ = Syndicate.__; return Syndicate.Patch.assert(this.ui.html('.todo-list',
|
.addAssertion((function() { var _ = Syndicate.__; return Syndicate.Patch.assert(this.ui.html('.todo-list',
|
||||||
Mustache.render(getTemplate(this.editing
|
Mustache.render(getTemplate(this.editing
|
||||||
|
@ -70,8 +70,8 @@ Syndicate.Actor.createFacet()
|
||||||
checked: completed ? "checked" : "",
|
checked: completed ? "checked" : "",
|
||||||
}),
|
}),
|
||||||
id), 0); }))
|
id), 0); }))
|
||||||
.onEvent(true, "retracted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(_cachedAssertion1468253138670_1, 0); }), (function() { var _ = Syndicate.__; return { assertion: _cachedAssertion1468253138670_1, metalevel: 0 }; }), (function() {})).completeBuild(); }))
|
.onEvent(true, "retracted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(_cachedAssertion1468253788491_1, 0); }), (function() { var _ = Syndicate.__; return { assertion: _cachedAssertion1468253788491_1, metalevel: 0 }; }), (function() {})).completeBuild(); }))
|
||||||
.onEvent(true, "retracted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(_cachedAssertion1468253138670_0, 0); }), (function() { var _ = Syndicate.__; return { assertion: _cachedAssertion1468253138670_0, metalevel: 0 }; }), (function() {})).completeBuild(); }))
|
.onEvent(true, "retracted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(_cachedAssertion1468253788491_0, 0); }), (function() { var _ = Syndicate.__; return { assertion: _cachedAssertion1468253788491_0, metalevel: 0 }; }), (function() {})).completeBuild(); }))
|
||||||
.onEvent(false, "message", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(this.ui.event('.toggle', 'change', _), 0); }), (function() { var _ = Syndicate.__; return { assertion: this.ui.event('.toggle', 'change', (Syndicate._$("e"))), metalevel: 0 }; }), (function(e) {
|
.onEvent(false, "message", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(this.ui.event('.toggle', 'change', _), 0); }), (function() { var _ = Syndicate.__; return { assertion: this.ui.event('.toggle', 'change', (Syndicate._$("e"))), metalevel: 0 }; }), (function(e) {
|
||||||
Syndicate.Dataspace.send(setCompleted(id, e.target.checked));
|
Syndicate.Dataspace.send(setCompleted(id, e.target.checked));
|
||||||
}))
|
}))
|
||||||
|
@ -119,31 +119,31 @@ Syndicate.Actor.createFacet()
|
||||||
(function () {
|
(function () {
|
||||||
Syndicate.Actor.createFacet()
|
Syndicate.Actor.createFacet()
|
||||||
.onEvent(false, "asserted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(activeTodoCount(_), 0); }), (function() { var _ = Syndicate.__; return { assertion: activeTodoCount((Syndicate._$("count"))), metalevel: 0 }; }), (function(count) {
|
.onEvent(false, "asserted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(activeTodoCount(_), 0); }), (function() { var _ = Syndicate.__; return { assertion: activeTodoCount((Syndicate._$("count"))), metalevel: 0 }; }), (function(count) {
|
||||||
var _cachedAssertion1468253138670_2 = (function() { var _ = Syndicate.__; return activeTodoCount(count); })();
|
var _cachedAssertion1468253788491_2 = (function() { var _ = Syndicate.__; return activeTodoCount(count); })();
|
||||||
Syndicate.Actor.createFacet()
|
Syndicate.Actor.createFacet()
|
||||||
.addAssertion((function() { var _ = Syndicate.__; return Syndicate.Patch.assert(this.ui.context('count').html('.todo-count strong', '' + count), 0); }))
|
.addAssertion((function() { var _ = Syndicate.__; return Syndicate.Patch.assert(this.ui.context('count').html('.todo-count strong', '' + count), 0); }))
|
||||||
.addAssertion((function() { var _ = Syndicate.__; return (count !== 1) ? Syndicate.Patch.assert(, 0) : Syndicate.Patch.emptyPatch; }))
|
.addAssertion((function() { var _ = Syndicate.__; return (count !== 1) ? Syndicate.Patch.assert(, 0) : Syndicate.Patch.emptyPatch; }))
|
||||||
.onEvent(true, "retracted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(_cachedAssertion1468253138670_2, 0); }), (function() { var _ = Syndicate.__; return { assertion: _cachedAssertion1468253138670_2, metalevel: 0 }; }), (function() {})).completeBuild(); }))
|
.onEvent(true, "retracted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(_cachedAssertion1468253788491_2, 0); }), (function() { var _ = Syndicate.__; return { assertion: _cachedAssertion1468253788491_2, metalevel: 0 }; }), (function() {})).completeBuild(); }))
|
||||||
.onEvent(false, "asserted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(totalTodoCount(0), 0); }), (function() { var _ = Syndicate.__; return { assertion: totalTodoCount(0), metalevel: 0 }; }), (function() {
|
.onEvent(false, "asserted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(totalTodoCount(0), 0); }), (function() { var _ = Syndicate.__; return { assertion: totalTodoCount(0), metalevel: 0 }; }), (function() {
|
||||||
var _cachedAssertion1468253138670_3 = (function() { var _ = Syndicate.__; return totalTodoCount(0); })();
|
var _cachedAssertion1468253788491_3 = (function() { var _ = Syndicate.__; return totalTodoCount(0); })();
|
||||||
Syndicate.Actor.createFacet()
|
Syndicate.Actor.createFacet()
|
||||||
.addAssertion((function() { var _ = Syndicate.__; return Syndicate.Patch.assert(Syndicate.UI.uiAttribute('section.main', 'class', 'hidden'), 0); }))
|
.addAssertion((function() { var _ = Syndicate.__; return Syndicate.Patch.assert(Syndicate.UI.uiAttribute('section.main', 'class', 'hidden'), 0); }))
|
||||||
.addAssertion((function() { var _ = Syndicate.__; return Syndicate.Patch.assert(Syndicate.UI.uiAttribute('footer.footer', 'class', 'hidden'), 0); }))
|
.addAssertion((function() { var _ = Syndicate.__; return Syndicate.Patch.assert(Syndicate.UI.uiAttribute('footer.footer', 'class', 'hidden'), 0); }))
|
||||||
.onEvent(true, "retracted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(_cachedAssertion1468253138670_3, 0); }), (function() { var _ = Syndicate.__; return { assertion: _cachedAssertion1468253138670_3, metalevel: 0 }; }), (function() {})).completeBuild(); }))
|
.onEvent(true, "retracted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(_cachedAssertion1468253788491_3, 0); }), (function() { var _ = Syndicate.__; return { assertion: _cachedAssertion1468253788491_3, metalevel: 0 }; }), (function() {})).completeBuild(); }))
|
||||||
.onEvent(false, "asserted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(completedTodoCount(0), 0); }), (function() { var _ = Syndicate.__; return { assertion: completedTodoCount(0), metalevel: 0 }; }), (function() {
|
.onEvent(false, "asserted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(completedTodoCount(0), 0); }), (function() { var _ = Syndicate.__; return { assertion: completedTodoCount(0), metalevel: 0 }; }), (function() {
|
||||||
var _cachedAssertion1468253138670_4 = (function() { var _ = Syndicate.__; return completedTodoCount(0); })();
|
var _cachedAssertion1468253788491_4 = (function() { var _ = Syndicate.__; return completedTodoCount(0); })();
|
||||||
Syndicate.Actor.createFacet()
|
Syndicate.Actor.createFacet()
|
||||||
.addAssertion((function() { var _ = Syndicate.__; return Syndicate.Patch.assert(Syndicate.UI.uiAttribute('button.clear-completed', 'class', 'hidden'), 0); }))
|
.addAssertion((function() { var _ = Syndicate.__; return Syndicate.Patch.assert(Syndicate.UI.uiAttribute('button.clear-completed', 'class', 'hidden'), 0); }))
|
||||||
.onEvent(true, "retracted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(_cachedAssertion1468253138670_4, 0); }), (function() { var _ = Syndicate.__; return { assertion: _cachedAssertion1468253138670_4, metalevel: 0 }; }), (function() {})).completeBuild(); }))
|
.onEvent(true, "retracted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(_cachedAssertion1468253788491_4, 0); }), (function() { var _ = Syndicate.__; return { assertion: _cachedAssertion1468253788491_4, metalevel: 0 }; }), (function() {})).completeBuild(); }))
|
||||||
.onEvent(false, "message", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(Syndicate.UI.globalEvent('button.clear-completed', 'click', _), 0); }), (function() { var _ = Syndicate.__; return { assertion: Syndicate.UI.globalEvent('button.clear-completed', 'click', _), metalevel: 0 }; }), (function() {
|
.onEvent(false, "message", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(Syndicate.UI.globalEvent('button.clear-completed', 'click', _), 0); }), (function() { var _ = Syndicate.__; return { assertion: Syndicate.UI.globalEvent('button.clear-completed', 'click', _), metalevel: 0 }; }), (function() {
|
||||||
Syndicate.Dataspace.send(clearCompletedTodos());
|
Syndicate.Dataspace.send(clearCompletedTodos());
|
||||||
}))
|
}))
|
||||||
.onEvent(false, "asserted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(allCompleted(), 0); }), (function() { var _ = Syndicate.__; return { assertion: allCompleted(), metalevel: 0 }; }), (function() {
|
.onEvent(false, "asserted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(allCompleted(), 0); }), (function() { var _ = Syndicate.__; return { assertion: allCompleted(), metalevel: 0 }; }), (function() {
|
||||||
var _cachedAssertion1468253138670_5 = (function() { var _ = Syndicate.__; return allCompleted(); })();
|
var _cachedAssertion1468253788491_5 = (function() { var _ = Syndicate.__; return allCompleted(); })();
|
||||||
Syndicate.Actor.createFacet()
|
Syndicate.Actor.createFacet()
|
||||||
.addInitBlock((function() { Syndicate.Dataspace.send(Syndicate.UI.setProperty('.toggle-all', 'checked', true)); }))
|
.addInitBlock((function() { Syndicate.Dataspace.send(Syndicate.UI.setProperty('.toggle-all', 'checked', true)); }))
|
||||||
.addDoneBlock((function() { Syndicate.Dataspace.send(Syndicate.UI.setProperty('.toggle-all', 'checked', false)); }))
|
.addDoneBlock((function() { Syndicate.Dataspace.send(Syndicate.UI.setProperty('.toggle-all', 'checked', false)); }))
|
||||||
.onEvent(true, "retracted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(_cachedAssertion1468253138670_5, 0); }), (function() { var _ = Syndicate.__; return { assertion: _cachedAssertion1468253138670_5, metalevel: 0 }; }), (function() {})).completeBuild(); }))
|
.onEvent(true, "retracted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(_cachedAssertion1468253788491_5, 0); }), (function() { var _ = Syndicate.__; return { assertion: _cachedAssertion1468253788491_5, metalevel: 0 }; }), (function() {})).completeBuild(); }))
|
||||||
.onEvent(false, "message", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(Syndicate.UI.globalEvent('.toggle-all', 'change', _), 0); }), (function() { var _ = Syndicate.__; return { assertion: Syndicate.UI.globalEvent('.toggle-all', 'change', (Syndicate._$("e"))), metalevel: 0 }; }), (function(e) {
|
.onEvent(false, "message", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(Syndicate.UI.globalEvent('.toggle-all', 'change', _), 0); }), (function() { var _ = Syndicate.__; return { assertion: Syndicate.UI.globalEvent('.toggle-all', 'change', (Syndicate._$("e"))), metalevel: 0 }; }), (function(e) {
|
||||||
Syndicate.Dataspace.send(setAllCompleted(e.target.checked));
|
Syndicate.Dataspace.send(setAllCompleted(e.target.checked));
|
||||||
}))
|
}))
|
||||||
|
@ -169,27 +169,27 @@ Syndicate.Actor.createFacet()
|
||||||
(function () {
|
(function () {
|
||||||
Syndicate.Actor.createFacet()
|
Syndicate.Actor.createFacet()
|
||||||
.onEvent(false, "asserted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(Syndicate.UI.locationHash(_), 0); }), (function() { var _ = Syndicate.__; return { assertion: Syndicate.UI.locationHash((Syndicate._$("hash"))), metalevel: 0 }; }), (function(hash) {
|
.onEvent(false, "asserted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(Syndicate.UI.locationHash(_), 0); }), (function() { var _ = Syndicate.__; return { assertion: Syndicate.UI.locationHash((Syndicate._$("hash"))), metalevel: 0 }; }), (function(hash) {
|
||||||
var _cachedAssertion1468253138670_6 = (function() { var _ = Syndicate.__; return Syndicate.UI.locationHash(hash); })();
|
var _cachedAssertion1468253788491_6 = (function() { var _ = Syndicate.__; return Syndicate.UI.locationHash(hash); })();
|
||||||
Syndicate.Actor.createFacet()
|
Syndicate.Actor.createFacet()
|
||||||
.addAssertion((function() { var _ = Syndicate.__; return Syndicate.Patch.assert(Syndicate.UI.uiAttribute('ul.filters > li > a[href="#'+hash+'"]',
|
.addAssertion((function() { var _ = Syndicate.__; return Syndicate.Patch.assert(Syndicate.UI.uiAttribute('ul.filters > li > a[href="#'+hash+'"]',
|
||||||
'class', 'selected'), 0); }))
|
'class', 'selected'), 0); }))
|
||||||
.onEvent(true, "retracted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(_cachedAssertion1468253138670_6, 0); }), (function() { var _ = Syndicate.__; return { assertion: _cachedAssertion1468253138670_6, metalevel: 0 }; }), (function() {})).completeBuild(); }))
|
.onEvent(true, "retracted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(_cachedAssertion1468253788491_6, 0); }), (function() { var _ = Syndicate.__; return { assertion: _cachedAssertion1468253788491_6, metalevel: 0 }; }), (function() {})).completeBuild(); }))
|
||||||
.onEvent(false, "asserted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(Syndicate.UI.locationHash('/'), 0); }), (function() { var _ = Syndicate.__; return { assertion: Syndicate.UI.locationHash('/'), metalevel: 0 }; }), (function() {
|
.onEvent(false, "asserted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(Syndicate.UI.locationHash('/'), 0); }), (function() { var _ = Syndicate.__; return { assertion: Syndicate.UI.locationHash('/'), metalevel: 0 }; }), (function() {
|
||||||
var _cachedAssertion1468253138670_7 = (function() { var _ = Syndicate.__; return Syndicate.UI.locationHash('/'); })();
|
var _cachedAssertion1468253788491_7 = (function() { var _ = Syndicate.__; return Syndicate.UI.locationHash('/'); })();
|
||||||
Syndicate.Actor.createFacet()
|
Syndicate.Actor.createFacet()
|
||||||
.addAssertion((function() { var _ = Syndicate.__; return Syndicate.Patch.assert(show(true), 0); }))
|
.addAssertion((function() { var _ = Syndicate.__; return Syndicate.Patch.assert(show(true), 0); }))
|
||||||
.addAssertion((function() { var _ = Syndicate.__; return Syndicate.Patch.assert(show(false), 0); }))
|
.addAssertion((function() { var _ = Syndicate.__; return Syndicate.Patch.assert(show(false), 0); }))
|
||||||
.onEvent(true, "retracted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(_cachedAssertion1468253138670_7, 0); }), (function() { var _ = Syndicate.__; return { assertion: _cachedAssertion1468253138670_7, metalevel: 0 }; }), (function() {})).completeBuild(); }))
|
.onEvent(true, "retracted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(_cachedAssertion1468253788491_7, 0); }), (function() { var _ = Syndicate.__; return { assertion: _cachedAssertion1468253788491_7, metalevel: 0 }; }), (function() {})).completeBuild(); }))
|
||||||
.onEvent(false, "asserted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(Syndicate.UI.locationHash('/active'), 0); }), (function() { var _ = Syndicate.__; return { assertion: Syndicate.UI.locationHash('/active'), metalevel: 0 }; }), (function() {
|
.onEvent(false, "asserted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(Syndicate.UI.locationHash('/active'), 0); }), (function() { var _ = Syndicate.__; return { assertion: Syndicate.UI.locationHash('/active'), metalevel: 0 }; }), (function() {
|
||||||
var _cachedAssertion1468253138670_8 = (function() { var _ = Syndicate.__; return Syndicate.UI.locationHash('/active'); })();
|
var _cachedAssertion1468253788491_8 = (function() { var _ = Syndicate.__; return Syndicate.UI.locationHash('/active'); })();
|
||||||
Syndicate.Actor.createFacet()
|
Syndicate.Actor.createFacet()
|
||||||
.addAssertion((function() { var _ = Syndicate.__; return Syndicate.Patch.assert(show(false), 0); }))
|
.addAssertion((function() { var _ = Syndicate.__; return Syndicate.Patch.assert(show(false), 0); }))
|
||||||
.onEvent(true, "retracted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(_cachedAssertion1468253138670_8, 0); }), (function() { var _ = Syndicate.__; return { assertion: _cachedAssertion1468253138670_8, metalevel: 0 }; }), (function() {})).completeBuild(); }))
|
.onEvent(true, "retracted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(_cachedAssertion1468253788491_8, 0); }), (function() { var _ = Syndicate.__; return { assertion: _cachedAssertion1468253788491_8, metalevel: 0 }; }), (function() {})).completeBuild(); }))
|
||||||
.onEvent(false, "asserted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(Syndicate.UI.locationHash('/completed'), 0); }), (function() { var _ = Syndicate.__; return { assertion: Syndicate.UI.locationHash('/completed'), metalevel: 0 }; }), (function() {
|
.onEvent(false, "asserted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(Syndicate.UI.locationHash('/completed'), 0); }), (function() { var _ = Syndicate.__; return { assertion: Syndicate.UI.locationHash('/completed'), metalevel: 0 }; }), (function() {
|
||||||
var _cachedAssertion1468253138670_9 = (function() { var _ = Syndicate.__; return Syndicate.UI.locationHash('/completed'); })();
|
var _cachedAssertion1468253788491_9 = (function() { var _ = Syndicate.__; return Syndicate.UI.locationHash('/completed'); })();
|
||||||
Syndicate.Actor.createFacet()
|
Syndicate.Actor.createFacet()
|
||||||
.addAssertion((function() { var _ = Syndicate.__; return Syndicate.Patch.assert(show(true), 0); }))
|
.addAssertion((function() { var _ = Syndicate.__; return Syndicate.Patch.assert(show(true), 0); }))
|
||||||
.onEvent(true, "retracted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(_cachedAssertion1468253138670_9, 0); }), (function() { var _ = Syndicate.__; return { assertion: _cachedAssertion1468253138670_9, metalevel: 0 }; }), (function() {})).completeBuild(); })).completeBuild(); })();
|
.onEvent(true, "retracted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(_cachedAssertion1468253788491_9, 0); }), (function() { var _ = Syndicate.__; return { assertion: _cachedAssertion1468253788491_9, metalevel: 0 }; }), (function() {})).completeBuild(); })).completeBuild(); })();
|
||||||
});
|
});
|
||||||
|
|
||||||
Syndicate.Actor.spawnActor(new Object(), function() {
|
Syndicate.Actor.spawnActor(new Object(), function() {
|
||||||
|
@ -218,20 +218,20 @@ Syndicate.Actor.createFacet()
|
||||||
todoListItemModel(db.nextId++, title, false);
|
todoListItemModel(db.nextId++, title, false);
|
||||||
}))
|
}))
|
||||||
.onEvent(false, "asserted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(todo(_, _, _), 0); }), (function() { var _ = Syndicate.__; return { assertion: todo((Syndicate._$("id")), _, _), metalevel: 0 }; }), (function(id) {
|
.onEvent(false, "asserted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(todo(_, _, _), 0); }), (function() { var _ = Syndicate.__; return { assertion: todo((Syndicate._$("id")), _, _), metalevel: 0 }; }), (function(id) {
|
||||||
var _cachedAssertion1468253138670_10 = (function() { var _ = Syndicate.__; return todo(id, _, _); })();
|
var _cachedAssertion1468253788491_10 = (function() { var _ = Syndicate.__; return todo(id, _, _); })();
|
||||||
Syndicate.Actor.createFacet()
|
Syndicate.Actor.createFacet()
|
||||||
.onEvent(false, "asserted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(todo(id, _, _), 0); }), (function() { var _ = Syndicate.__; return { assertion: todo(id, (Syndicate._$("title")), (Syndicate._$("completed"))), metalevel: 0 }; }), (function(title, completed) {
|
.onEvent(false, "asserted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(todo(id, _, _), 0); }), (function() { var _ = Syndicate.__; return { assertion: todo(id, (Syndicate._$("title")), (Syndicate._$("completed"))), metalevel: 0 }; }), (function(title, completed) {
|
||||||
var _cachedAssertion1468253138670_11 = (function() { var _ = Syndicate.__; return todo(id, title, completed); })();
|
var _cachedAssertion1468253788491_11 = (function() { var _ = Syndicate.__; return todo(id, title, completed); })();
|
||||||
Syndicate.Actor.createFacet()
|
Syndicate.Actor.createFacet()
|
||||||
.addInitBlock((function() {
|
.addInitBlock((function() {
|
||||||
db.todos[id] = {id: id, title: title, completed: completed};
|
db.todos[id] = {id: id, title: title, completed: completed};
|
||||||
localStorage['todos-syndicate'] = JSON.stringify(db);
|
localStorage['todos-syndicate'] = JSON.stringify(db);
|
||||||
}))
|
}))
|
||||||
.onEvent(true, "retracted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(_cachedAssertion1468253138670_11, 0); }), (function() { var _ = Syndicate.__; return { assertion: _cachedAssertion1468253138670_11, metalevel: 0 }; }), (function() {})).completeBuild(); }))
|
.onEvent(true, "retracted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(_cachedAssertion1468253788491_11, 0); }), (function() { var _ = Syndicate.__; return { assertion: _cachedAssertion1468253788491_11, metalevel: 0 }; }), (function() {})).completeBuild(); }))
|
||||||
.addDoneBlock((function() {
|
.addDoneBlock((function() {
|
||||||
delete db.todos[id];
|
delete db.todos[id];
|
||||||
localStorage['todos-syndicate'] = JSON.stringify(db);
|
localStorage['todos-syndicate'] = JSON.stringify(db);
|
||||||
}))
|
}))
|
||||||
.onEvent(true, "retracted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(_cachedAssertion1468253138670_10, 0); }), (function() { var _ = Syndicate.__; return { assertion: _cachedAssertion1468253138670_10, metalevel: 0 }; }), (function() {})).completeBuild(); })).completeBuild(); })();
|
.onEvent(true, "retracted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(_cachedAssertion1468253788491_10, 0); }), (function() { var _ = Syndicate.__; return { assertion: _cachedAssertion1468253788491_10, metalevel: 0 }; }), (function() {})).completeBuild(); })).completeBuild(); })();
|
||||||
});
|
});
|
||||||
}).startStepping();
|
}).startStepping();
|
||||||
|
|
|
@ -2,13 +2,15 @@
|
||||||
var Syndicate = require('../../src/main.js');
|
var Syndicate = require('../../src/main.js');
|
||||||
/// -->
|
/// -->
|
||||||
|
|
||||||
|
/// # {{ page.title }}
|
||||||
|
///
|
||||||
/// This is an extended two-buyer book-purchase protocol, based
|
/// This is an extended two-buyer book-purchase protocol, based
|
||||||
/// loosely on an example given in:
|
/// loosely on an example given in:
|
||||||
///
|
///
|
||||||
/// > K. Honda, N. Yoshida, and M. Carbone, “Multiparty asynchronous
|
/// > K. Honda, N. Yoshida, and M. Carbone, “Multiparty asynchronous
|
||||||
/// > session types,” POPL 2008.
|
/// > session types,” POPL 2008.
|
||||||
|
|
||||||
/// # The Scenario
|
/// ## The Scenario
|
||||||
///
|
///
|
||||||
/// A book-seller responds to requests for book prices when asked. A
|
/// A book-seller responds to requests for book prices when asked. A
|
||||||
/// pair of prospective buyers run through a shopping list. For each
|
/// pair of prospective buyers run through a shopping list. For each
|
||||||
|
@ -18,9 +20,9 @@ var Syndicate = require('../../src/main.js');
|
||||||
/// different split. If the second buyer agrees to a split, it then
|
/// different split. If the second buyer agrees to a split, it then
|
||||||
/// negotiates the purchase of the book with the book-seller.
|
/// negotiates the purchase of the book with the book-seller.
|
||||||
|
|
||||||
/// # The Protocol
|
/// ## The Protocol
|
||||||
|
|
||||||
/// ## Role: SELLER
|
/// ### Role: SELLER
|
||||||
///
|
///
|
||||||
/// - when interest in `bookQuote($title, _)` appears,
|
/// - when interest in `bookQuote($title, _)` appears,
|
||||||
/// asserts `bookQuote(title, Maybe Float)`, `false` meaning not available,
|
/// asserts `bookQuote(title, Maybe Float)`, `false` meaning not available,
|
||||||
|
@ -29,17 +31,17 @@ var Syndicate = require('../../src/main.js');
|
||||||
/// asserts `order(title, offer-price, false, false)` for "no sale", otherwise
|
/// asserts `order(title, offer-price, false, false)` for "no sale", otherwise
|
||||||
/// `order(title, offer-price, PositiveInteger, String)`, an accepted sale.
|
/// `order(title, offer-price, PositiveInteger, String)`, an accepted sale.
|
||||||
|
|
||||||
/// ## Role: BUYER
|
/// ### Role: BUYER
|
||||||
///
|
///
|
||||||
/// - observes `bookQuote(title, $price)` to learn prices.
|
/// - observes `bookQuote(title, $price)` to learn prices.
|
||||||
/// - observes `order(title, offer-price, $id, $delivery-date)` to make orders.
|
/// - observes `order(title, offer-price, $id, $delivery-date)` to make orders.
|
||||||
|
|
||||||
/// ## Role: SPLIT-PROPOSER
|
/// ### Role: SPLIT-PROPOSER
|
||||||
///
|
///
|
||||||
/// - observes `splitProposal(title, asking-price, contribution, $accepted)`
|
/// - observes `splitProposal(title, asking-price, contribution, $accepted)`
|
||||||
/// to make a split-proposal and learn whether it was accepted or not.
|
/// to make a split-proposal and learn whether it was accepted or not.
|
||||||
|
|
||||||
/// ## Role: SPLIT-DISPOSER
|
/// ### Role: SPLIT-DISPOSER
|
||||||
///
|
///
|
||||||
/// - when interest in `splitProposal($title, $asking-price, $contribution, _)`
|
/// - when interest in `splitProposal($title, $asking-price, $contribution, _)`
|
||||||
/// appears, asserts `splitProposal(title, askingPrice, contribution, true)`
|
/// appears, asserts `splitProposal(title, askingPrice, contribution, true)`
|
||||||
|
@ -48,7 +50,7 @@ var Syndicate = require('../../src/main.js');
|
||||||
/// `splitProposal(title, asking-price, contribution, false)` to indicate they
|
/// `splitProposal(title, asking-price, contribution, false)` to indicate they
|
||||||
/// are unwilling to go through with the deal.
|
/// are unwilling to go through with the deal.
|
||||||
|
|
||||||
/// # A Sample Run
|
/// ## A Sample Run
|
||||||
///
|
///
|
||||||
/// Run the program with `../../bin/syndicatec index.js | node` from a
|
/// Run the program with `../../bin/syndicatec index.js | node` from a
|
||||||
/// checkout of the Syndicate repository.
|
/// checkout of the Syndicate repository.
|
||||||
|
@ -90,9 +92,9 @@ var Syndicate = require('../../src/main.js');
|
||||||
/// A has bought everything they wanted!
|
/// A has bought everything they wanted!
|
||||||
/// The order for The Wind in the Willows has id 10001485, and will be delivered on March 9th
|
/// The order for The Wind in the Willows has id 10001485, and will be delivered on March 9th
|
||||||
|
|
||||||
/// # The Code
|
/// ## The Code
|
||||||
|
|
||||||
/// ## Type Declarations
|
/// ### Type Declarations
|
||||||
|
|
||||||
/// First, we declare *assertion types* for our protocol.
|
/// First, we declare *assertion types* for our protocol.
|
||||||
|
|
||||||
|
@ -101,7 +103,7 @@ var order = Syndicate.Struct.makeConstructor("order", ["title","price","id","del
|
||||||
|
|
||||||
var splitProposal = Syndicate.Struct.makeConstructor("splitProposal", ["title","price","contribution","accepted"]);
|
var splitProposal = Syndicate.Struct.makeConstructor("splitProposal", ["title","price","contribution","accepted"]);
|
||||||
|
|
||||||
/// ## Utilities
|
/// ### Utilities
|
||||||
|
|
||||||
/// This routine is under consideration for possible addition to the
|
/// This routine is under consideration for possible addition to the
|
||||||
/// core library.
|
/// core library.
|
||||||
|
@ -113,7 +115,7 @@ Syndicate.Actor.createFacet()
|
||||||
.onEvent(true, "retracted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(Syndicate.observe(P), 0); }), (function() { var _ = Syndicate.__; return { assertion: Syndicate.observe(P), metalevel: 0 }; }), (function() {})).completeBuild(); })();
|
.onEvent(true, "retracted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(Syndicate.observe(P), 0); }), (function() { var _ = Syndicate.__; return { assertion: Syndicate.observe(P), metalevel: 0 }; }), (function() {})).completeBuild(); })();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ## Implementation: SELLER
|
/// ### Implementation: SELLER
|
||||||
|
|
||||||
function seller() {
|
function seller() {
|
||||||
Syndicate.Actor.spawnActor(new Object(), function() {
|
Syndicate.Actor.spawnActor(new Object(), function() {
|
||||||
|
@ -129,16 +131,23 @@ function seller() {
|
||||||
};
|
};
|
||||||
this.nextOrderId = 10001483;
|
this.nextOrderId = 10001483;
|
||||||
|
|
||||||
|
/// Looking up a price yields `false` if no such book is in our
|
||||||
|
/// inventory.
|
||||||
|
|
||||||
|
this.priceOf = function (title) {
|
||||||
|
return (title in this.books) && this.books[title];
|
||||||
|
};
|
||||||
|
|
||||||
/// The seller responds to interest in bookQuotes by asserting a
|
/// The seller responds to interest in bookQuotes by asserting a
|
||||||
/// responsive record, if one exists.
|
/// responsive record, if one exists.
|
||||||
|
|
||||||
(function () {
|
(function () {
|
||||||
Syndicate.Actor.createFacet()
|
Syndicate.Actor.createFacet()
|
||||||
.onEvent(false, "asserted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(Syndicate.observe(bookQuote(_, _)), 0); }), (function() { var _ = Syndicate.__; return { assertion: Syndicate.observe(bookQuote((Syndicate._$("title")), _)), metalevel: 0 }; }), (function(title) {
|
.onEvent(false, "asserted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(Syndicate.observe(bookQuote(_, _)), 0); }), (function() { var _ = Syndicate.__; return { assertion: Syndicate.observe(bookQuote((Syndicate._$("title")), _)), metalevel: 0 }; }), (function(title) {
|
||||||
var _cachedAssertion1468253139911_0 = (function() { var _ = Syndicate.__; return Syndicate.observe(bookQuote(title, _)); })();
|
var _cachedAssertion1468253789712_0 = (function() { var _ = Syndicate.__; return Syndicate.observe(bookQuote(title, _)); })();
|
||||||
Syndicate.Actor.createFacet()
|
Syndicate.Actor.createFacet()
|
||||||
.addAssertion((function() { var _ = Syndicate.__; return Syndicate.Patch.assert(bookQuote(title, title in this.books ? this.books[title] : false), 0); }))
|
.addAssertion((function() { var _ = Syndicate.__; return Syndicate.Patch.assert(bookQuote(title, this.priceOf(title)), 0); }))
|
||||||
.onEvent(true, "retracted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(_cachedAssertion1468253139911_0, 0); }), (function() { var _ = Syndicate.__; return { assertion: _cachedAssertion1468253139911_0, metalevel: 0 }; }), (function() {})).completeBuild(); })).completeBuild(); })();
|
.onEvent(true, "retracted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(_cachedAssertion1468253789712_0, 0); }), (function() { var _ = Syndicate.__; return { assertion: _cachedAssertion1468253789712_0, metalevel: 0 }; }), (function() {})).completeBuild(); })).completeBuild(); })();
|
||||||
|
|
||||||
/// It also responds to order requests.
|
/// It also responds to order requests.
|
||||||
|
|
||||||
|
@ -149,9 +158,10 @@ Syndicate.Actor.createFacet()
|
||||||
/// We cannot sell a book we do not have, and we will not sell for
|
/// We cannot sell a book we do not have, and we will not sell for
|
||||||
/// less than our asking price.
|
/// less than our asking price.
|
||||||
|
|
||||||
var askingPrice = title in this.books ? this.books[title] : false;
|
var askingPrice = this.priceOf(title);
|
||||||
if ((askingPrice === false) || (offerPrice < askingPrice)) {
|
if ((askingPrice === false) || (offerPrice < askingPrice)) {
|
||||||
whileRelevantAssert(order(title, offerPrice, false, false));
|
whileRelevantAssert(
|
||||||
|
order(title, offerPrice, false, false));
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
/// But if we can sell it, we do so by allocating an order ID and
|
/// But if we can sell it, we do so by allocating an order ID and
|
||||||
|
@ -161,14 +171,15 @@ Syndicate.Actor.createFacet()
|
||||||
delete this.books[title];
|
delete this.books[title];
|
||||||
|
|
||||||
Syndicate.Actor.spawnActor(new Object(), function() {
|
Syndicate.Actor.spawnActor(new Object(), function() {
|
||||||
whileRelevantAssert(order(title, offerPrice, orderId, "March 9th"));
|
whileRelevantAssert(
|
||||||
|
order(title, offerPrice, orderId, "March 9th"));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
})).completeBuild(); })();
|
})).completeBuild(); })();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ## Implementation: SPLIT-PROPOSER and book-quote-requestor
|
/// ### Implementation: SPLIT-PROPOSER and book-quote-requestor
|
||||||
|
|
||||||
function buyerA() {
|
function buyerA() {
|
||||||
Syndicate.Actor.spawnActor(new Object(), function() {
|
Syndicate.Actor.spawnActor(new Object(), function() {
|
||||||
|
@ -205,7 +216,8 @@ Syndicate.Actor.createFacet()
|
||||||
console.log("A learns that "+title+" is out-of-stock.");
|
console.log("A learns that "+title+" is out-of-stock.");
|
||||||
buyBooks();
|
buyBooks();
|
||||||
} else {
|
} else {
|
||||||
console.log("A learns that the price of "+title+" is "+price);
|
console.log("A learns that the price of "+title+
|
||||||
|
" is "+price);
|
||||||
|
|
||||||
/// Next, repeatedly make split offers to a SPLIT-DISPOSER until
|
/// Next, repeatedly make split offers to a SPLIT-DISPOSER until
|
||||||
/// either one is accepted, or the contribution from the
|
/// either one is accepted, or the contribution from the
|
||||||
|
@ -236,19 +248,23 @@ Syndicate.Actor.createFacet()
|
||||||
(function () {
|
(function () {
|
||||||
Syndicate.Actor.createFacet()
|
Syndicate.Actor.createFacet()
|
||||||
.onEvent(true, "asserted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(splitProposal(title, price, contribution, true), 0); }), (function() { var _ = Syndicate.__; return { assertion: splitProposal(title, price, contribution, true), metalevel: 0 }; }), (function() {
|
.onEvent(true, "asserted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(splitProposal(title, price, contribution, true), 0); }), (function() { var _ = Syndicate.__; return { assertion: splitProposal(title, price, contribution, true), metalevel: 0 }; }), (function() {
|
||||||
console.log("A learns that the split-proposal for "+title+" was accepted");
|
console.log("A learns that the split-proposal for "+
|
||||||
|
title+" was accepted");
|
||||||
buyBooks();
|
buyBooks();
|
||||||
}))
|
}))
|
||||||
.onEvent(true, "asserted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(splitProposal(title, price, contribution, false), 0); }), (function() { var _ = Syndicate.__; return { assertion: splitProposal(title, price, contribution, false), metalevel: 0 }; }), (function() {
|
.onEvent(true, "asserted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(splitProposal(title, price, contribution, false), 0); }), (function() { var _ = Syndicate.__; return { assertion: splitProposal(title, price, contribution, false), metalevel: 0 }; }), (function() {
|
||||||
console.log("A learns that the split-proposal for "+title+" was rejected");
|
console.log("A learns that the split-proposal for "+
|
||||||
trySplit(title, price, contribution + ((price - contribution) / 2));
|
title+" was rejected");
|
||||||
|
trySplit(title,
|
||||||
|
price,
|
||||||
|
contribution + ((price - contribution) / 2));
|
||||||
})).completeBuild(); })();
|
})).completeBuild(); })();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ## Implementation: SPLIT-DISPOSER and BUYER
|
/// ### Implementation: SPLIT-DISPOSER and BUYER
|
||||||
|
|
||||||
function buyerB() {
|
function buyerB() {
|
||||||
Syndicate.Actor.spawnActor(new Object(), function() {
|
Syndicate.Actor.spawnActor(new Object(), function() {
|
||||||
|
@ -263,16 +279,24 @@ function buyerB() {
|
||||||
|
|
||||||
(function () {
|
(function () {
|
||||||
Syndicate.Actor.createFacet()
|
Syndicate.Actor.createFacet()
|
||||||
.onEvent(false, "asserted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(Syndicate.observe(splitProposal(_, _, _, _)), 0); }), (function() { var _ = Syndicate.__; return { assertion: Syndicate.observe(splitProposal((Syndicate._$("title")), (Syndicate._$("price")), (Syndicate._$("theirContribution")), _)), metalevel: 0 }; }), (function(title, price, theirContribution) {
|
.onEvent(false, "asserted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(Syndicate.observe(splitProposal(_,
|
||||||
|
_,
|
||||||
|
_,
|
||||||
|
_)), 0); }), (function() { var _ = Syndicate.__; return { assertion: Syndicate.observe(splitProposal((Syndicate._$("title")),
|
||||||
|
(Syndicate._$("price")),
|
||||||
|
(Syndicate._$("theirContribution")),
|
||||||
|
_)), metalevel: 0 }; }), (function(title, price, theirContribution) {
|
||||||
var myContribution = price - theirContribution;
|
var myContribution = price - theirContribution;
|
||||||
console.log("B is being asked to contribute "+myContribution+" toward "+title+
|
console.log("B is being asked to contribute "+myContribution+
|
||||||
" at price "+price);
|
" toward "+title+" at price "+price);
|
||||||
|
|
||||||
/// We may not be able to afford contributing this much.
|
/// We may not be able to afford contributing this much.
|
||||||
|
|
||||||
if (myContribution > this.funds) {
|
if (myContribution > this.funds) {
|
||||||
console.log("B hasn't enough funds ("+this.funds+" remaining)");
|
console.log("B hasn't enough funds ("+this.funds+
|
||||||
whileRelevantAssert(splitProposal(title, price, theirContribution, false));
|
" remaining)");
|
||||||
|
whileRelevantAssert(
|
||||||
|
splitProposal(title, price, theirContribution, false));
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
/// But if we *can* afford it, update our remaining funds and spawn a
|
/// But if we *can* afford it, update our remaining funds and spawn a
|
||||||
|
@ -280,13 +304,17 @@ Syndicate.Actor.createFacet()
|
||||||
/// on a split.
|
/// on a split.
|
||||||
|
|
||||||
var remainingFunds = this.funds - myContribution;
|
var remainingFunds = this.funds - myContribution;
|
||||||
console.log("B accepts the offer, leaving them with "+remainingFunds+" remaining funds");
|
console.log("B accepts the offer, leaving them with "+
|
||||||
|
remainingFunds+" remaining funds");
|
||||||
this.funds = remainingFunds;
|
this.funds = remainingFunds;
|
||||||
|
|
||||||
Syndicate.Actor.spawnActor(new Object(), function() {
|
Syndicate.Actor.spawnActor(new Object(), function() {
|
||||||
(function () {
|
(function () {
|
||||||
Syndicate.Actor.createFacet()
|
Syndicate.Actor.createFacet()
|
||||||
.addAssertion((function() { var _ = Syndicate.__; return Syndicate.Patch.assert(splitProposal(title, price, theirContribution, true), 0); }))
|
.addAssertion((function() { var _ = Syndicate.__; return Syndicate.Patch.assert(splitProposal(title,
|
||||||
|
price,
|
||||||
|
theirContribution,
|
||||||
|
true), 0); }))
|
||||||
.onEvent(true, "asserted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(order(title, price, _, _), 0); }), (function() { var _ = Syndicate.__; return { assertion: order(title, price, (Syndicate._$("id")), (Syndicate._$("date"))), metalevel: 0 }; }), (function(id, date) {
|
.onEvent(true, "asserted", (function() { var _ = Syndicate.__; return Syndicate.Patch.sub(order(title, price, _, _), 0); }), (function() { var _ = Syndicate.__; return { assertion: order(title, price, (Syndicate._$("id")), (Syndicate._$("date"))), metalevel: 0 }; }), (function(id, date) {
|
||||||
console.log("The order for "+title+" has id "+id+
|
console.log("The order for "+title+" has id "+id+
|
||||||
", and will be delivered on "+date);
|
", and will be delivered on "+date);
|
||||||
|
@ -297,7 +325,7 @@ Syndicate.Actor.createFacet()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ## Starting Configuration
|
/// ### Starting Configuration
|
||||||
|
|
||||||
new Syndicate.Ground(function () {
|
new Syndicate.Ground(function () {
|
||||||
seller();
|
seller();
|
||||||
|
|
|
@ -6,13 +6,15 @@
|
||||||
var Syndicate = require('../../src/main.js');
|
var Syndicate = require('../../src/main.js');
|
||||||
/// -->
|
/// -->
|
||||||
|
|
||||||
|
/// # {{ page.title }}
|
||||||
|
///
|
||||||
/// This is an extended two-buyer book-purchase protocol, based
|
/// This is an extended two-buyer book-purchase protocol, based
|
||||||
/// loosely on an example given in:
|
/// loosely on an example given in:
|
||||||
///
|
///
|
||||||
/// > K. Honda, N. Yoshida, and M. Carbone, “Multiparty asynchronous
|
/// > K. Honda, N. Yoshida, and M. Carbone, “Multiparty asynchronous
|
||||||
/// > session types,” POPL 2008.
|
/// > session types,” POPL 2008.
|
||||||
|
|
||||||
/// # The Scenario
|
/// ## The Scenario
|
||||||
///
|
///
|
||||||
/// A book-seller responds to requests for book prices when asked. A
|
/// A book-seller responds to requests for book prices when asked. A
|
||||||
/// pair of prospective buyers run through a shopping list. For each
|
/// pair of prospective buyers run through a shopping list. For each
|
||||||
|
@ -22,9 +24,9 @@ var Syndicate = require('../../src/main.js');
|
||||||
/// different split. If the second buyer agrees to a split, it then
|
/// different split. If the second buyer agrees to a split, it then
|
||||||
/// negotiates the purchase of the book with the book-seller.
|
/// negotiates the purchase of the book with the book-seller.
|
||||||
|
|
||||||
/// # The Protocol
|
/// ## The Protocol
|
||||||
|
|
||||||
/// ## Role: SELLER
|
/// ### Role: SELLER
|
||||||
///
|
///
|
||||||
/// - when interest in `bookQuote($title, _)` appears,
|
/// - when interest in `bookQuote($title, _)` appears,
|
||||||
/// asserts `bookQuote(title, Maybe Float)`, `false` meaning not available,
|
/// asserts `bookQuote(title, Maybe Float)`, `false` meaning not available,
|
||||||
|
@ -33,17 +35,17 @@ var Syndicate = require('../../src/main.js');
|
||||||
/// asserts `order(title, offer-price, false, false)` for "no sale", otherwise
|
/// asserts `order(title, offer-price, false, false)` for "no sale", otherwise
|
||||||
/// `order(title, offer-price, PositiveInteger, String)`, an accepted sale.
|
/// `order(title, offer-price, PositiveInteger, String)`, an accepted sale.
|
||||||
|
|
||||||
/// ## Role: BUYER
|
/// ### Role: BUYER
|
||||||
///
|
///
|
||||||
/// - observes `bookQuote(title, $price)` to learn prices.
|
/// - observes `bookQuote(title, $price)` to learn prices.
|
||||||
/// - observes `order(title, offer-price, $id, $delivery-date)` to make orders.
|
/// - observes `order(title, offer-price, $id, $delivery-date)` to make orders.
|
||||||
|
|
||||||
/// ## Role: SPLIT-PROPOSER
|
/// ### Role: SPLIT-PROPOSER
|
||||||
///
|
///
|
||||||
/// - observes `splitProposal(title, asking-price, contribution, $accepted)`
|
/// - observes `splitProposal(title, asking-price, contribution, $accepted)`
|
||||||
/// to make a split-proposal and learn whether it was accepted or not.
|
/// to make a split-proposal and learn whether it was accepted or not.
|
||||||
|
|
||||||
/// ## Role: SPLIT-DISPOSER
|
/// ### Role: SPLIT-DISPOSER
|
||||||
///
|
///
|
||||||
/// - when interest in `splitProposal($title, $asking-price, $contribution, _)`
|
/// - when interest in `splitProposal($title, $asking-price, $contribution, _)`
|
||||||
/// appears, asserts `splitProposal(title, askingPrice, contribution, true)`
|
/// appears, asserts `splitProposal(title, askingPrice, contribution, true)`
|
||||||
|
@ -52,7 +54,7 @@ var Syndicate = require('../../src/main.js');
|
||||||
/// `splitProposal(title, asking-price, contribution, false)` to indicate they
|
/// `splitProposal(title, asking-price, contribution, false)` to indicate they
|
||||||
/// are unwilling to go through with the deal.
|
/// are unwilling to go through with the deal.
|
||||||
|
|
||||||
/// # A Sample Run
|
/// ## A Sample Run
|
||||||
///
|
///
|
||||||
/// Run the program with `../../bin/syndicatec index.js | node` from a
|
/// Run the program with `../../bin/syndicatec index.js | node` from a
|
||||||
/// checkout of the Syndicate repository.
|
/// checkout of the Syndicate repository.
|
||||||
|
@ -94,9 +96,9 @@ var Syndicate = require('../../src/main.js');
|
||||||
/// A has bought everything they wanted!
|
/// A has bought everything they wanted!
|
||||||
/// The order for The Wind in the Willows has id 10001485, and will be delivered on March 9th
|
/// The order for The Wind in the Willows has id 10001485, and will be delivered on March 9th
|
||||||
|
|
||||||
/// # The Code
|
/// ## The Code
|
||||||
|
|
||||||
/// ## Type Declarations
|
/// ### Type Declarations
|
||||||
|
|
||||||
/// First, we declare *assertion types* for our protocol.
|
/// First, we declare *assertion types* for our protocol.
|
||||||
|
|
||||||
|
@ -105,7 +107,7 @@ assertion type order(title, price, id, deliveryDate);
|
||||||
|
|
||||||
assertion type splitProposal(title, price, contribution, accepted);
|
assertion type splitProposal(title, price, contribution, accepted);
|
||||||
|
|
||||||
/// ## Utilities
|
/// ### Utilities
|
||||||
|
|
||||||
/// This routine is under consideration for possible addition to the
|
/// This routine is under consideration for possible addition to the
|
||||||
/// core library.
|
/// core library.
|
||||||
|
@ -118,7 +120,7 @@ function whileRelevantAssert(P) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ## Implementation: SELLER
|
/// ### Implementation: SELLER
|
||||||
|
|
||||||
function seller() {
|
function seller() {
|
||||||
actor {
|
actor {
|
||||||
|
@ -134,26 +136,36 @@ function seller() {
|
||||||
};
|
};
|
||||||
this.nextOrderId = 10001483;
|
this.nextOrderId = 10001483;
|
||||||
|
|
||||||
|
/// Looking up a price yields `false` if no such book is in our
|
||||||
|
/// inventory.
|
||||||
|
|
||||||
|
this.priceOf = function (title) {
|
||||||
|
return (title in this.books) && this.books[title];
|
||||||
|
};
|
||||||
|
|
||||||
/// The seller responds to interest in bookQuotes by asserting a
|
/// The seller responds to interest in bookQuotes by asserting a
|
||||||
/// responsive record, if one exists.
|
/// responsive record, if one exists.
|
||||||
|
|
||||||
react {
|
react {
|
||||||
during Syndicate.observe(bookQuote($title, _)) {
|
during Syndicate.observe(bookQuote($title, _)) {
|
||||||
assert bookQuote(title, title in this.books ? this.books[title] : false);
|
assert bookQuote(title, this.priceOf(title));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// It also responds to order requests.
|
/// It also responds to order requests.
|
||||||
|
|
||||||
react {
|
react {
|
||||||
on asserted Syndicate.observe(order($title, $offerPrice, _, _)) {
|
on asserted
|
||||||
|
Syndicate.observe(order($title, $offerPrice, _, _))
|
||||||
|
{
|
||||||
|
|
||||||
/// We cannot sell a book we do not have, and we will not sell for
|
/// We cannot sell a book we do not have, and we will not sell for
|
||||||
/// less than our asking price.
|
/// less than our asking price.
|
||||||
|
|
||||||
var askingPrice = title in this.books ? this.books[title] : false;
|
var askingPrice = this.priceOf(title);
|
||||||
if ((askingPrice === false) || (offerPrice < askingPrice)) {
|
if ((askingPrice === false) || (offerPrice < askingPrice)) {
|
||||||
whileRelevantAssert(order(title, offerPrice, false, false));
|
whileRelevantAssert(
|
||||||
|
order(title, offerPrice, false, false));
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
/// But if we can sell it, we do so by allocating an order ID and
|
/// But if we can sell it, we do so by allocating an order ID and
|
||||||
|
@ -163,7 +175,8 @@ function seller() {
|
||||||
delete this.books[title];
|
delete this.books[title];
|
||||||
|
|
||||||
actor {
|
actor {
|
||||||
whileRelevantAssert(order(title, offerPrice, orderId, "March 9th"));
|
whileRelevantAssert(
|
||||||
|
order(title, offerPrice, orderId, "March 9th"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -171,7 +184,7 @@ function seller() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ## Implementation: SPLIT-PROPOSER and book-quote-requestor
|
/// ### Implementation: SPLIT-PROPOSER and book-quote-requestor
|
||||||
|
|
||||||
function buyerA() {
|
function buyerA() {
|
||||||
actor {
|
actor {
|
||||||
|
@ -207,7 +220,8 @@ function buyerA() {
|
||||||
console.log("A learns that "+title+" is out-of-stock.");
|
console.log("A learns that "+title+" is out-of-stock.");
|
||||||
buyBooks();
|
buyBooks();
|
||||||
} else {
|
} else {
|
||||||
console.log("A learns that the price of "+title+" is "+price);
|
console.log("A learns that the price of "+title+
|
||||||
|
" is "+price);
|
||||||
|
|
||||||
/// Next, repeatedly make split offers to a SPLIT-DISPOSER until
|
/// Next, repeatedly make split offers to a SPLIT-DISPOSER until
|
||||||
/// either one is accepted, or the contribution from the
|
/// either one is accepted, or the contribution from the
|
||||||
|
@ -237,14 +251,22 @@ function buyerA() {
|
||||||
/// Make our proposal, and wait for a response.
|
/// Make our proposal, and wait for a response.
|
||||||
|
|
||||||
react until {
|
react until {
|
||||||
case asserted splitProposal(title, price, contribution, true) {
|
case asserted
|
||||||
console.log("A learns that the split-proposal for "+title+" was accepted");
|
splitProposal(title, price, contribution, true)
|
||||||
|
{
|
||||||
|
console.log("A learns that the split-proposal for "+
|
||||||
|
title+" was accepted");
|
||||||
buyBooks();
|
buyBooks();
|
||||||
}
|
}
|
||||||
|
|
||||||
case asserted splitProposal(title, price, contribution, false) {
|
case asserted
|
||||||
console.log("A learns that the split-proposal for "+title+" was rejected");
|
splitProposal(title, price, contribution, false)
|
||||||
trySplit(title, price, contribution + ((price - contribution) / 2));
|
{
|
||||||
|
console.log("A learns that the split-proposal for "+
|
||||||
|
title+" was rejected");
|
||||||
|
trySplit(title,
|
||||||
|
price,
|
||||||
|
contribution + ((price - contribution) / 2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -252,7 +274,7 @@ function buyerA() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ## Implementation: SPLIT-DISPOSER and BUYER
|
/// ### Implementation: SPLIT-DISPOSER and BUYER
|
||||||
|
|
||||||
function buyerB() {
|
function buyerB() {
|
||||||
actor {
|
actor {
|
||||||
|
@ -266,16 +288,23 @@ function buyerB() {
|
||||||
/// `splitProposal`.
|
/// `splitProposal`.
|
||||||
|
|
||||||
react {
|
react {
|
||||||
on asserted Syndicate.observe(splitProposal($title, $price, $theirContribution, _)) {
|
on asserted
|
||||||
|
Syndicate.observe(splitProposal($title,
|
||||||
|
$price,
|
||||||
|
$theirContribution,
|
||||||
|
_))
|
||||||
|
{
|
||||||
var myContribution = price - theirContribution;
|
var myContribution = price - theirContribution;
|
||||||
console.log("B is being asked to contribute "+myContribution+" toward "+title+
|
console.log("B is being asked to contribute "+myContribution+
|
||||||
" at price "+price);
|
" toward "+title+" at price "+price);
|
||||||
|
|
||||||
/// We may not be able to afford contributing this much.
|
/// We may not be able to afford contributing this much.
|
||||||
|
|
||||||
if (myContribution > this.funds) {
|
if (myContribution > this.funds) {
|
||||||
console.log("B hasn't enough funds ("+this.funds+" remaining)");
|
console.log("B hasn't enough funds ("+this.funds+
|
||||||
whileRelevantAssert(splitProposal(title, price, theirContribution, false));
|
" remaining)");
|
||||||
|
whileRelevantAssert(
|
||||||
|
splitProposal(title, price, theirContribution, false));
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
/// But if we *can* afford it, update our remaining funds and spawn a
|
/// But if we *can* afford it, update our remaining funds and spawn a
|
||||||
|
@ -283,7 +312,8 @@ function buyerB() {
|
||||||
/// on a split.
|
/// on a split.
|
||||||
|
|
||||||
var remainingFunds = this.funds - myContribution;
|
var remainingFunds = this.funds - myContribution;
|
||||||
console.log("B accepts the offer, leaving them with "+remainingFunds+" remaining funds");
|
console.log("B accepts the offer, leaving them with "+
|
||||||
|
remainingFunds+" remaining funds");
|
||||||
this.funds = remainingFunds;
|
this.funds = remainingFunds;
|
||||||
|
|
||||||
actor {
|
actor {
|
||||||
|
@ -292,7 +322,10 @@ function buyerB() {
|
||||||
/// While waiting for order confirmation, take the opportunity to
|
/// While waiting for order confirmation, take the opportunity to
|
||||||
/// signal to our SPLIT-PROPOSER that we accepted their proposal.
|
/// signal to our SPLIT-PROPOSER that we accepted their proposal.
|
||||||
|
|
||||||
assert splitProposal(title, price, theirContribution, true);
|
assert splitProposal(title,
|
||||||
|
price,
|
||||||
|
theirContribution,
|
||||||
|
true);
|
||||||
|
|
||||||
/// When order confirmation arrives, this purchase is completed.
|
/// When order confirmation arrives, this purchase is completed.
|
||||||
|
|
||||||
|
@ -309,7 +342,7 @@ function buyerB() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ## Starting Configuration
|
/// ### Starting Configuration
|
||||||
|
|
||||||
ground dataspace {
|
ground dataspace {
|
||||||
seller();
|
seller();
|
||||||
|
|
|
@ -6,13 +6,15 @@ title: Two-Party Buyer Protocol
|
||||||
var Syndicate = require('../../src/main.js');
|
var Syndicate = require('../../src/main.js');
|
||||||
-->
|
-->
|
||||||
|
|
||||||
|
# {{ page.title }}
|
||||||
|
|
||||||
This is an extended two-buyer book-purchase protocol, based
|
This is an extended two-buyer book-purchase protocol, based
|
||||||
loosely on an example given in:
|
loosely on an example given in:
|
||||||
|
|
||||||
> K. Honda, N. Yoshida, and M. Carbone, “Multiparty asynchronous
|
> K. Honda, N. Yoshida, and M. Carbone, “Multiparty asynchronous
|
||||||
> session types,” POPL 2008.
|
> session types,” POPL 2008.
|
||||||
|
|
||||||
# The Scenario
|
## The Scenario
|
||||||
|
|
||||||
A book-seller responds to requests for book prices when asked. A
|
A book-seller responds to requests for book prices when asked. A
|
||||||
pair of prospective buyers run through a shopping list. For each
|
pair of prospective buyers run through a shopping list. For each
|
||||||
|
@ -22,9 +24,9 @@ otherwise, it rejects the offer, and the first buyer tries a
|
||||||
different split. If the second buyer agrees to a split, it then
|
different split. If the second buyer agrees to a split, it then
|
||||||
negotiates the purchase of the book with the book-seller.
|
negotiates the purchase of the book with the book-seller.
|
||||||
|
|
||||||
# The Protocol
|
## The Protocol
|
||||||
|
|
||||||
## Role: SELLER
|
### Role: SELLER
|
||||||
|
|
||||||
- when interest in `bookQuote($title, _)` appears,
|
- when interest in `bookQuote($title, _)` appears,
|
||||||
asserts `bookQuote(title, Maybe Float)`, `false` meaning not available,
|
asserts `bookQuote(title, Maybe Float)`, `false` meaning not available,
|
||||||
|
@ -33,17 +35,17 @@ negotiates the purchase of the book with the book-seller.
|
||||||
asserts `order(title, offer-price, false, false)` for "no sale", otherwise
|
asserts `order(title, offer-price, false, false)` for "no sale", otherwise
|
||||||
`order(title, offer-price, PositiveInteger, String)`, an accepted sale.
|
`order(title, offer-price, PositiveInteger, String)`, an accepted sale.
|
||||||
|
|
||||||
## Role: BUYER
|
### Role: BUYER
|
||||||
|
|
||||||
- observes `bookQuote(title, $price)` to learn prices.
|
- observes `bookQuote(title, $price)` to learn prices.
|
||||||
- observes `order(title, offer-price, $id, $delivery-date)` to make orders.
|
- observes `order(title, offer-price, $id, $delivery-date)` to make orders.
|
||||||
|
|
||||||
## Role: SPLIT-PROPOSER
|
### Role: SPLIT-PROPOSER
|
||||||
|
|
||||||
- observes `splitProposal(title, asking-price, contribution, $accepted)`
|
- observes `splitProposal(title, asking-price, contribution, $accepted)`
|
||||||
to make a split-proposal and learn whether it was accepted or not.
|
to make a split-proposal and learn whether it was accepted or not.
|
||||||
|
|
||||||
## Role: SPLIT-DISPOSER
|
### Role: SPLIT-DISPOSER
|
||||||
|
|
||||||
- when interest in `splitProposal($title, $asking-price, $contribution, _)`
|
- when interest in `splitProposal($title, $asking-price, $contribution, _)`
|
||||||
appears, asserts `splitProposal(title, askingPrice, contribution, true)`
|
appears, asserts `splitProposal(title, askingPrice, contribution, true)`
|
||||||
|
@ -52,7 +54,7 @@ negotiates the purchase of the book with the book-seller.
|
||||||
`splitProposal(title, asking-price, contribution, false)` to indicate they
|
`splitProposal(title, asking-price, contribution, false)` to indicate they
|
||||||
are unwilling to go through with the deal.
|
are unwilling to go through with the deal.
|
||||||
|
|
||||||
# A Sample Run
|
## A Sample Run
|
||||||
|
|
||||||
Run the program with `../../bin/syndicatec index.js | node` from a
|
Run the program with `../../bin/syndicatec index.js | node` from a
|
||||||
checkout of the Syndicate repository.
|
checkout of the Syndicate repository.
|
||||||
|
@ -94,9 +96,9 @@ checkout of the Syndicate repository.
|
||||||
A has bought everything they wanted!
|
A has bought everything they wanted!
|
||||||
The order for The Wind in the Willows has id 10001485, and will be delivered on March 9th
|
The order for The Wind in the Willows has id 10001485, and will be delivered on March 9th
|
||||||
|
|
||||||
# The Code
|
## The Code
|
||||||
|
|
||||||
## Type Declarations
|
### Type Declarations
|
||||||
|
|
||||||
First, we declare *assertion types* for our protocol.
|
First, we declare *assertion types* for our protocol.
|
||||||
|
|
||||||
|
@ -105,7 +107,7 @@ First, we declare *assertion types* for our protocol.
|
||||||
|
|
||||||
assertion type splitProposal(title, price, contribution, accepted);
|
assertion type splitProposal(title, price, contribution, accepted);
|
||||||
|
|
||||||
## Utilities
|
### Utilities
|
||||||
|
|
||||||
This routine is under consideration for possible addition to the
|
This routine is under consideration for possible addition to the
|
||||||
core library.
|
core library.
|
||||||
|
@ -118,7 +120,7 @@ core library.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
## Implementation: SELLER
|
### Implementation: SELLER
|
||||||
|
|
||||||
function seller() {
|
function seller() {
|
||||||
actor {
|
actor {
|
||||||
|
@ -134,26 +136,36 @@ tracking the next order ID to be allocated.
|
||||||
};
|
};
|
||||||
this.nextOrderId = 10001483;
|
this.nextOrderId = 10001483;
|
||||||
|
|
||||||
|
Looking up a price yields `false` if no such book is in our
|
||||||
|
inventory.
|
||||||
|
|
||||||
|
this.priceOf = function (title) {
|
||||||
|
return (title in this.books) && this.books[title];
|
||||||
|
};
|
||||||
|
|
||||||
The seller responds to interest in bookQuotes by asserting a
|
The seller responds to interest in bookQuotes by asserting a
|
||||||
responsive record, if one exists.
|
responsive record, if one exists.
|
||||||
|
|
||||||
react {
|
react {
|
||||||
during Syndicate.observe(bookQuote($title, _)) {
|
during Syndicate.observe(bookQuote($title, _)) {
|
||||||
assert bookQuote(title, title in this.books ? this.books[title] : false);
|
assert bookQuote(title, this.priceOf(title));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
It also responds to order requests.
|
It also responds to order requests.
|
||||||
|
|
||||||
react {
|
react {
|
||||||
on asserted Syndicate.observe(order($title, $offerPrice, _, _)) {
|
on asserted
|
||||||
|
Syndicate.observe(order($title, $offerPrice, _, _))
|
||||||
|
{
|
||||||
|
|
||||||
We cannot sell a book we do not have, and we will not sell for
|
We cannot sell a book we do not have, and we will not sell for
|
||||||
less than our asking price.
|
less than our asking price.
|
||||||
|
|
||||||
var askingPrice = title in this.books ? this.books[title] : false;
|
var askingPrice = this.priceOf(title);
|
||||||
if ((askingPrice === false) || (offerPrice < askingPrice)) {
|
if ((askingPrice === false) || (offerPrice < askingPrice)) {
|
||||||
whileRelevantAssert(order(title, offerPrice, false, false));
|
whileRelevantAssert(
|
||||||
|
order(title, offerPrice, false, false));
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
But if we can sell it, we do so by allocating an order ID and
|
But if we can sell it, we do so by allocating an order ID and
|
||||||
|
@ -163,7 +175,8 @@ replying to the orderer.
|
||||||
delete this.books[title];
|
delete this.books[title];
|
||||||
|
|
||||||
actor {
|
actor {
|
||||||
whileRelevantAssert(order(title, offerPrice, orderId, "March 9th"));
|
whileRelevantAssert(
|
||||||
|
order(title, offerPrice, orderId, "March 9th"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -171,7 +184,7 @@ replying to the orderer.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
## Implementation: SPLIT-PROPOSER and book-quote-requestor
|
### Implementation: SPLIT-PROPOSER and book-quote-requestor
|
||||||
|
|
||||||
function buyerA() {
|
function buyerA() {
|
||||||
actor {
|
actor {
|
||||||
|
@ -207,7 +220,8 @@ First, retrieve a quote for the title, and analyze the result.
|
||||||
console.log("A learns that "+title+" is out-of-stock.");
|
console.log("A learns that "+title+" is out-of-stock.");
|
||||||
buyBooks();
|
buyBooks();
|
||||||
} else {
|
} else {
|
||||||
console.log("A learns that the price of "+title+" is "+price);
|
console.log("A learns that the price of "+title+
|
||||||
|
" is "+price);
|
||||||
|
|
||||||
Next, repeatedly make split offers to a SPLIT-DISPOSER until
|
Next, repeatedly make split offers to a SPLIT-DISPOSER until
|
||||||
either one is accepted, or the contribution from the
|
either one is accepted, or the contribution from the
|
||||||
|
@ -237,14 +251,22 @@ perform the BUYER role here.
|
||||||
Make our proposal, and wait for a response.
|
Make our proposal, and wait for a response.
|
||||||
|
|
||||||
react until {
|
react until {
|
||||||
case asserted splitProposal(title, price, contribution, true) {
|
case asserted
|
||||||
console.log("A learns that the split-proposal for "+title+" was accepted");
|
splitProposal(title, price, contribution, true)
|
||||||
|
{
|
||||||
|
console.log("A learns that the split-proposal for "+
|
||||||
|
title+" was accepted");
|
||||||
buyBooks();
|
buyBooks();
|
||||||
}
|
}
|
||||||
|
|
||||||
case asserted splitProposal(title, price, contribution, false) {
|
case asserted
|
||||||
console.log("A learns that the split-proposal for "+title+" was rejected");
|
splitProposal(title, price, contribution, false)
|
||||||
trySplit(title, price, contribution + ((price - contribution) / 2));
|
{
|
||||||
|
console.log("A learns that the split-proposal for "+
|
||||||
|
title+" was rejected");
|
||||||
|
trySplit(title,
|
||||||
|
price,
|
||||||
|
contribution + ((price - contribution) / 2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -252,7 +274,7 @@ Make our proposal, and wait for a response.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
## Implementation: SPLIT-DISPOSER and BUYER
|
### Implementation: SPLIT-DISPOSER and BUYER
|
||||||
|
|
||||||
function buyerB() {
|
function buyerB() {
|
||||||
actor {
|
actor {
|
||||||
|
@ -266,16 +288,23 @@ It spends its time waiting for a SPLIT-PROPOSER to offer a
|
||||||
`splitProposal`.
|
`splitProposal`.
|
||||||
|
|
||||||
react {
|
react {
|
||||||
on asserted Syndicate.observe(splitProposal($title, $price, $theirContribution, _)) {
|
on asserted
|
||||||
|
Syndicate.observe(splitProposal($title,
|
||||||
|
$price,
|
||||||
|
$theirContribution,
|
||||||
|
_))
|
||||||
|
{
|
||||||
var myContribution = price - theirContribution;
|
var myContribution = price - theirContribution;
|
||||||
console.log("B is being asked to contribute "+myContribution+" toward "+title+
|
console.log("B is being asked to contribute "+myContribution+
|
||||||
" at price "+price);
|
" toward "+title+" at price "+price);
|
||||||
|
|
||||||
We may not be able to afford contributing this much.
|
We may not be able to afford contributing this much.
|
||||||
|
|
||||||
if (myContribution > this.funds) {
|
if (myContribution > this.funds) {
|
||||||
console.log("B hasn't enough funds ("+this.funds+" remaining)");
|
console.log("B hasn't enough funds ("+this.funds+
|
||||||
whileRelevantAssert(splitProposal(title, price, theirContribution, false));
|
" remaining)");
|
||||||
|
whileRelevantAssert(
|
||||||
|
splitProposal(title, price, theirContribution, false));
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
But if we *can* afford it, update our remaining funds and spawn a
|
But if we *can* afford it, update our remaining funds and spawn a
|
||||||
|
@ -283,7 +312,8 @@ small actor to handle the actual purchase now that we have agreed
|
||||||
on a split.
|
on a split.
|
||||||
|
|
||||||
var remainingFunds = this.funds - myContribution;
|
var remainingFunds = this.funds - myContribution;
|
||||||
console.log("B accepts the offer, leaving them with "+remainingFunds+" remaining funds");
|
console.log("B accepts the offer, leaving them with "+
|
||||||
|
remainingFunds+" remaining funds");
|
||||||
this.funds = remainingFunds;
|
this.funds = remainingFunds;
|
||||||
|
|
||||||
actor {
|
actor {
|
||||||
|
@ -292,7 +322,10 @@ on a split.
|
||||||
While waiting for order confirmation, take the opportunity to
|
While waiting for order confirmation, take the opportunity to
|
||||||
signal to our SPLIT-PROPOSER that we accepted their proposal.
|
signal to our SPLIT-PROPOSER that we accepted their proposal.
|
||||||
|
|
||||||
assert splitProposal(title, price, theirContribution, true);
|
assert splitProposal(title,
|
||||||
|
price,
|
||||||
|
theirContribution,
|
||||||
|
true);
|
||||||
|
|
||||||
When order confirmation arrives, this purchase is completed.
|
When order confirmation arrives, this purchase is completed.
|
||||||
|
|
||||||
|
@ -309,7 +342,7 @@ When order confirmation arrives, this purchase is completed.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
## Starting Configuration
|
### Starting Configuration
|
||||||
|
|
||||||
ground dataspace {
|
ground dataspace {
|
||||||
seller();
|
seller();
|
||||||
|
|
Loading…
Reference in New Issue