-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmarket.py
132 lines (92 loc) · 3.82 KB
/
market.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#!/usr/bin/env python3
import asyncio
import signal
from autobahn.asyncio.component import Component
from autobahn.asyncio.component import run
from demo_config import create_autobahn_component_config
from demo_config import MARKET_BIDDER_ADD
from demo_config import MARKET_BIDDER_GONE
from demo_config import MARKET_GET
from demo_config import MARKET_ITEM_ADDED
from demo_config import MARKET_ITEM_BID
from demo_config import MARKET_ITEM_EXPIRED
from demo_config import MARKET_ITEM_GET
from demo_config import MARKET_ITEM_NEW_PRICE
from demo_config import MARKET_ITEM_SELL
from demo_config import MARKET_ITEM_SOLD
from demo_config import MARKET_OPENED
from item import Item
class Market:
def __init__(self):
ab_component_config = create_autobahn_component_config(user_id="market")
self._component = Component(**ab_component_config)
self._component.on("join", self._on_join)
self._session = None
self._items = {}
self._bidders = set()
def run(self):
run([self._component])
def _on_join(self, session, details):
self._session = session
self._session.register(self._get_items, MARKET_GET)
self._session.register(self._get_item, MARKET_ITEM_GET)
self._session.register(self._on_new_item, MARKET_ITEM_SELL)
self._session.register(self._on_bid, MARKET_ITEM_BID)
self._session.register(self._on_new_bidder, MARKET_BIDDER_ADD)
self._session.register(self._on_bidder_gone, MARKET_BIDDER_GONE)
print("Market ready to accept new items and bids")
self._session.publish(MARKET_OPENED)
def _on_new_bidder(self, name):
if not name or name in self._bidders:
return False
else:
print(f"New bidder: {name}")
self._bidders.add(name)
return True
def _on_bidder_gone(self, name):
if not name or name not in self._bidders:
return
print(f"{name} left, cancel thier bids.")
self._bidders.remove(name)
for item in self._items.values():
if item.is_on_offer() and item.winner == name:
item.winner = None
def _get_items(self):
return [item.wamp_pack() for item in self._items.values()]
def _get_item(self, name):
item = self._items.get(name)
return item.wamp_pack() if item is not None else None
def _on_new_item(self, name, price, deadline):
if name in self._items:
return False
item = Item(name, price, deadline)
self._items[name] = item
loop = asyncio.get_running_loop()
loop.call_later(item.timeout(), self._on_item_timeout, item)
print(f"New item starting at ${item.price} until {item.deadline_as_HMS()}.")
self._session.publish(MARKET_ITEM_ADDED, **item.wamp_pack())
return True
def _on_item_timeout(self, item):
print(f"Item '{item.name}' timed out at ${item.price} from {item.winner}")
topic = MARKET_ITEM_SOLD if item.winner else MARKET_ITEM_EXPIRED
self._session.publish(topic, **item.wamp_pack())
def _on_bid(self, item_name, bid, bidder_name):
if bidder_name not in self._bidders:
return False
item = self._items.get(item_name)
if item is None:
return False
if item.bid(bid, bidder_name):
print(f"Bid: '{item.name}' at ${item.price} from {bidder_name} ACCEPTED")
self._session.publish(MARKET_ITEM_NEW_PRICE, **item.wamp_pack())
return True
else:
print(f"Bid: '{item.name}' at ${item.price} from {bidder_name} REJECTED")
return False
if __name__ == "__main__":
# Handle Ctrl+C gracefully
def signal_handler(sig, frame):
sys.exit(0)
signal.signal(signal.SIGINT, signal_handler)
market = Market()
market.run()