Contract con_poker_hand_controller_v1


Contract Code


  
1 # con_poker_hand_controller_v1
2
3 import con_rsa_encryption as rsa
4 import con_otp_v1 as otp
5 import con_hand_evaluator_v1 as evaluator
6
7 random.seed()
8
9 ONE_CARD_POKER = 0
10 BLIND_POKER = 1
11 STUD_POKER = 2
12 HOLDEM_POKER = 3
13 OMAHA_POKER = 4
14 MAX_RANDOM_NUMBER = 99999999
15 NO_LIMIT = 0
16 POT_LIMIT = 1
17 FLOP = 1
18 TURN = 2
19 RIVER = 3
20
21 def get_players_and_assert_exists(game_id: str, games: Any) -> dict:
22 players = games[game_id, 'players']
23 assert players is not None, f'Game {game_id} does not exist.'
24 return players
25
26
27 def active_player_sort(players: list) -> int:
28 def sort(player):
29 return players.index(player)
30 return sort
31
32
33 def create_hand_id(name: str) -> str:
34 return hashlib.sha3(":".join([name, str(now)]))
35
36
37 @export
38 def start_hand(game_id: str, dealer: str, games: Any, hands: Any) -> str:
39 players = get_players_and_assert_exists(game_id, games)
40 assert dealer in players, 'You are not a part of this game.'
41 assert len(players) > 1, 'You cannot start a hand by yourself.'
42
43 previous_hand_id = games[game_id, 'current_hand']
44 if previous_hand_id is not None:
45 assert hands[previous_hand_id, 'payed_out'], 'The previous hand has not been payed out yet.'
46
47 hand_id = create_hand_id(name=game_id)
48 # Update game state
49 games[game_id, 'current_hand'] = hand_id
50 # Update hand state
51 hands[hand_id, 'game_id'] = game_id
52 hands[hand_id, 'dealer'] = dealer
53 hands[hand_id, 'folded'] = []
54 hands[hand_id, 'completed'] = False
55 hands[hand_id, 'payed_out'] = False
56 hands[hand_id, 'reached_dealer'] = False
57 hands[hand_id, 'active_players'] = []
58 hands[hand_id, 'current_bet'] = 0
59 hands[hand_id, 'pot'] = 0
60 hands[hand_id, 'all_in'] = []
61 return hand_id
62
63 @export
64 def ante_up(hand_id: str, player: str, games: Any, hands: Any):
65 game_id = hands[hand_id, 'game_id']
66 assert game_id is not None, 'This game does not exist.'
67 players = get_players_and_assert_exists(game_id, games)
68 assert player in players, 'You are not a part of this game.'
69 ante = games[game_id, 'ante']
70 chips = games[game_id, player]
71 assert chips is not None and chips >= ante, 'You do not have enough chips.'
72 active_players = hands[hand_id, 'active_players'] or []
73 assert player not in active_players, 'You have already paid the ante.'
74 game_type = games[game_id, 'game_type']
75 if game_type == STUD_POKER:
76 max_players = 52 // games[game_id, 'n_cards_total']
77 elif game_type == HOLDEM_POKER:
78 max_players = 10
79 elif game_type == OMAHA_POKER:
80 max_players = 10
81 else:
82 max_players = 50
83 assert len(active_players) < max_players, f'A maximum of {max_players} is allowed for this game type.'
84 # Pay ante
85 hands[hand_id, player, 'bet'] = ante
86 hands[hand_id, player, 'max_bet'] = chips
87 games[game_id, player] -= ante
88 # Update hand state
89 active_players.append(player)
90 active_players.sort(key=active_player_sort(players))
91 hands[hand_id, 'active_players'] = active_players
92 hands[hand_id, 'current_bet'] = ante
93 hands[hand_id, 'pot'] += ante
94 if chips == ante:
95 # All in
96 all_in = hands[hand_id, 'all_in']
97 all_in.append(player)
98 hands[hand_id, 'all_in'] = all_in
99
100
101 @export
102 def deal_cards(hand_id: str, dealer: str, games: Any, hands: Any, player_metadata: Any):
103
104 active_players = hands[hand_id, 'active_players']
105
106 assert dealer == hands[hand_id, 'dealer'], 'You are not the dealer.'
107 assert len(active_players) > 1, f'Not enough active players: {len(active_players)} <= 1'
108 assert dealer in active_players, 'You are not actively part of this hand.'
109
110 game_id = hands[hand_id, 'game_id']
111 game_type = games[game_id, 'game_type']
112
113 cards = evaluator.get_deck()
114
115 n_cards_total = games[game_id, 'n_cards_total']
116 n_hole_cards = games[game_id, 'n_hole_cards']
117
118 if game_type == HOLDEM_POKER or game_type == OMAHA_POKER:
119 community_cards = [",".join(cards[0:3]), cards[3], cards[4]]
120 else:
121 community_cards = None
122
123 for i in range(len(active_players)):
124 player = active_players[i]
125 player_key = player_metadata[player, 'public_rsa_key']
126 assert player_key is not None, f'Player {player} has not setup their encryption keys.'
127 keys = player_key.split('|')
128 assert len(keys) == 2, 'Invalid keys'
129
130 if game_type == ONE_CARD_POKER:
131 player_hand = cards[i: i+1]
132 elif game_type == BLIND_POKER:
133 # Player's hand is actually everyone elses hand
134 player_hand = cards[0:i] + cards[i+1:len(active_players)]
135 assert len(player_hand) == len(active_players)-1, f'Something went wrong. {len(player_hand)} != {len(active_players)-1}'
136 elif game_type == STUD_POKER:
137 player_hand = cards[n_cards_total*i:n_cards_total*i+n_cards_total]
138 assert len(player_hand) == n_cards_total, 'Something went wrong.'
139 elif game_type == HOLDEM_POKER:
140 player_hand = cards[5+2*i:5+2*i+2]
141 elif game_type == OMAHA_POKER:
142 player_hand = cards[5+4*i:5+4*i+4]
143 else:
144 assert False, 'Invalid game type.'
145
146 player_hand_str = ",".join(player_hand)
147
148 if n_hole_cards is not None and n_hole_cards < n_cards_total:
149 public_hand_str = ",".join(player_hand[n_hole_cards:])
150 else:
151 public_hand_str = None
152
153 salt = str(random.randint(0, MAX_RANDOM_NUMBER))
154
155 if community_cards is not None:
156 pad1 = otp.generate_otp(80)
157 pad2 = otp.generate_otp(20)
158 pad3 = otp.generate_otp(20)
159 salt1 = str(random.randint(0, MAX_RANDOM_NUMBER))
160 salt2 = str(random.randint(0, MAX_RANDOM_NUMBER))
161 salt3 = str(random.randint(0, MAX_RANDOM_NUMBER))
162 if i == 0:
163 community_cards[0] = otp.encrypt(community_cards[0], pad1, safe=False)
164 community_cards[1] = otp.encrypt(community_cards[1], pad2, safe=False)
165 community_cards[2] = otp.encrypt(community_cards[2], pad3, safe=False)
166 else:
167 community_cards[0] = otp.encrypt_hex(community_cards[0], pad1, safe=False)
168 community_cards[1] = otp.encrypt_hex(community_cards[1], pad2, safe=False)
169 community_cards[2] = otp.encrypt_hex(community_cards[2], pad3, safe=False)
170 pad1_with_salt = f'{pad1}:{salt1}'
171 pad2_with_salt = f'{pad2}:{salt2}'
172 pad3_with_salt = f'{pad3}:{salt3}'
173 encrypted_pad1 = rsa.encrypt(
174 message_str=pad1_with_salt,
175 n=int(keys[0]),
176 e=int(keys[1])
177 )
178 encrypted_pad2 = rsa.encrypt(
179 message_str=pad2_with_salt,
180 n=int(keys[0]),
181 e=int(keys[1])
182 )
183 encrypted_pad3 = rsa.encrypt(
184 message_str=pad3_with_salt,
185 n=int(keys[0]),
186 e=int(keys[1])
187 )
188 hands[hand_id, player, 'player_encrypted_pad1'] = encrypted_pad1
189 hands[hand_id, player, 'player_encrypted_pad2'] = encrypted_pad2
190 hands[hand_id, player, 'player_encrypted_pad3'] = encrypted_pad3
191 hands[hand_id, player, 'house_encrypted_pad1'] = hashlib.sha3(pad1_with_salt)
192 hands[hand_id, player, 'house_encrypted_pad2'] = hashlib.sha3(pad2_with_salt)
193 hands[hand_id, player, 'house_encrypted_pad3'] = hashlib.sha3(pad3_with_salt)
194
195 player_hand_str_with_salt = f'{player_hand_str}:{salt}'
196
197 # Encrypt players hand with their personal keys
198 player_encrypted_hand = rsa.encrypt(
199 message_str=player_hand_str_with_salt,
200 n=int(keys[0]),
201 e=int(keys[1])
202 )
203
204 # For verification purposes
205 house_encrypted_hand = hashlib.sha3(player_hand_str_with_salt)
206
207 if public_hand_str is not None:
208 hands[hand_id, player, 'public_hand'] = public_hand_str
209 hands[hand_id, player, 'player_encrypted_hand'] = player_encrypted_hand
210 hands[hand_id, player, 'house_encrypted_hand'] = house_encrypted_hand
211
212 # Update hand state
213 all_in = hands[hand_id, 'all_in']
214 hands[hand_id, 'next_better'] = evaluator.get_next_better(active_players, [], all_in, dealer)
215 if community_cards is not None:
216 hands[hand_id, 'community_encrypted'] = community_cards
217 hands[hand_id, 'community'] = [None, None, None]
218
219
220 def handle_done_betting(hand_id: str, game_type: int, next_better: str, active_players: list, folded: list, all_in: list, dealer: str, hands: Any) -> str:
221 if game_type == HOLDEM_POKER or game_type == OMAHA_POKER:
222 # multi rounds
223 round = hands[hand_id, 'round'] or 0
224 round += 1
225 hands[hand_id, 'round'] = round
226 if round == 4:
227 hands[hand_id, 'completed'] = True
228 else:
229 # Update stuff
230 hands[hand_id, 'full_circle'] = False
231 next_better = evaluator.get_next_better(
232 active_players, folded, all_in, dealer
233 )
234 hands[hand_id, 'first_better'] = next_better
235 else:
236 hands[hand_id, 'completed'] = True
237 return next_better
238
239
240 @export
241 def bet_check_or_fold(hand_id: str, bet: float, player: str, games: Any, hands: Any):
242 assert hands[hand_id, player, 'player_encrypted_hand'] is not None, 'Hand does not exist'
243 assert not hands[hand_id, 'completed'], 'This hand has already completed.'
244 assert hands[hand_id, 'next_better'] == player, 'It is not your turn to bet.'
245
246 active_players = hands[hand_id, 'active_players']
247 folded = hands[hand_id, 'folded']
248 all_in = hands[hand_id, 'all_in']
249
250 orig_all_in = all_in.copy()
251
252 call_bet = hands[hand_id, 'current_bet'] or 0
253 player_previous_bet = hands[hand_id, player, 'bet'] or 0
254 dealer = hands[hand_id, 'dealer']
255
256 next_better = evaluator.get_next_better(active_players, folded, all_in, player)
257
258 if dealer == player or (next_better is not None and next_better == hands[hand_id, 'first_better']):
259 # Been around the circle once
260 hands[hand_id, 'full_circle'] = True
261 full_circle = True
262 else:
263 full_circle = hands[hand_id, 'full_circle']
264
265 if next_better is None:
266 # No need to bet, this is the end of the hand
267 hands[hand_id, 'completed'] = True
268 else:
269 game_id = hands[hand_id, 'game_id']
270 game_type = games[game_id, 'game_type']
271 next_players_bet = hands[hand_id, next_better, 'bet']
272 if bet < 0:
273 # Folding
274 folded.append(player)
275 hands[hand_id, 'folded'] = folded
276 if player in all_in:
277 all_in.remove(player)
278 hands[hand_id, 'all_in'] = all_in
279 if len(folded) == len(active_players) - 1:
280 hands[hand_id, 'completed'] = True
281 current_bet = call_bet
282 else:
283 if bet == 0:
284 # Checking
285 max_bet = hands[hand_id, player, 'max_bet']
286 if max_bet == player_previous_bet and player not in all_in:
287 all_in.append(player)
288 hands[hand_id, 'all_in'] = all_in
289 current_bet = player_previous_bet
290 else:
291 # Betting
292 assert games[game_id, player] >= bet, 'You do not have enough chips to make this bet'
293 bet_type = games[game_id, 'bet_type']
294 if bet_type == POT_LIMIT:
295 pot = hands[hand_id, 'pot']
296 assert bet <= pot, f'Cannot overbet the pot in pot-limit mode.'
297 current_bet = player_previous_bet + bet
298 max_bet = hands[hand_id, player, 'max_bet']
299 if max_bet == current_bet and player not in all_in:
300 all_in.append(player)
301 hands[hand_id, 'all_in'] = all_in
302 hands[hand_id, player, 'bet'] = current_bet
303 hands[hand_id, 'current_bet'] = current_bet
304 hands[hand_id, 'pot'] += bet
305 games[game_id, player] -= bet
306 assert max_bet == current_bet or current_bet >= call_bet, 'Current bet is above your bet and you did not go all in.'
307 if next_players_bet is not None and next_players_bet == current_bet and full_circle:
308 next_better = handle_done_betting(hand_id, game_type, next_better, active_players, folded, orig_all_in, dealer, hands)
309
310 hands[hand_id, 'next_better'] = next_better
311
312
313 @export
314 def reveal_otp(hand_id: str, pad: int, salt: int, index: int, player: str, hands: Any):
315 assert index in (FLOP, TURN, RIVER), 'Invalid index.'
316 active_players = hands[hand_id, 'active_players']
317 assert active_players is not None, 'This hand does not exist.'
318 player_index = active_players.index(player)
319 assert player_index >= 0, 'You are not in this hand.'
320 # verify authenticity of key
321 assert hashlib.sha3(f'{pad}:{salt}') == hands[hand_id, player, f'house_encrypted_pad{index}'], 'Invalid key or salt.'
322 hands[hand_id, player, f'pad{index}'] = pad
323
324
325 @export
326 def reveal(hand_id: str, index: int, hands: Any) -> str:
327 assert index in (FLOP, TURN, RIVER), 'Invalid index.'
328 active_players = hands[hand_id, 'active_players']
329 community = hands[hand_id, 'community']
330 enc = hands[hand_id, 'community_encrypted'][index-1]
331 n_players = len(active_players)
332 for i in range(n_players):
333 player = active_players[-1-i]
334 pad = hands[hand_id, player, f'pad{index}']
335 assert pad is not None, f'Player {player} has not revealed their pad.'
336 if i != n_players - 1:
337 enc = otp.decrypt_hex(
338 encrypted_str=enc,
339 otp=pad,
340 safe=False
341 )
342 else:
343 enc = otp.decrypt(
344 encrypted_str=enc,
345 otp=pad,
346 safe=False
347 )
348 community[index-1] = enc
349 hands[hand_id, 'community'] = community
350 return enc
351
352
353 @export
354 def verify_hand(hand_id: str, player_hand_str: str, player: str, games: Any, hands: Any) -> str:
355 assert hands[hand_id, 'completed'], 'This hand has not completed yet.'
356 folded = hands[hand_id, 'folded']
357 assert player not in folded, 'No need to verify your hand because you folded.'
358 active_players = hands[hand_id, 'active_players']
359 assert player in active_players, 'You are not an active player in this hand.'
360
361 # Check if player has bet enough
362 bet_should_equal = hands[hand_id, 'current_bet']
363 assert bet_should_equal is not None, 'There is no current bet.'
364
365 player_bet = hands[hand_id, player, 'bet']
366 assert player_bet is not None, 'You have not bet yet.'
367
368 assert bet_should_equal == player_bet or player in hands[hand_id, 'all_in'], 'Bets have not stabilized.'
369
370 # For verification purposes
371 house_encrypted_hand = hashlib.sha3(player_hand_str)
372
373 previous_house_encrypted_hand = hands[hand_id, player, 'house_encrypted_hand']
374
375 verified = previous_house_encrypted_hand is not None and \
376 previous_house_encrypted_hand == house_encrypted_hand
377
378 if not verified:
379 # BAD ACTOR NEEDS TO BE PUNISHED
380 folded.append(player)
381 hands[hand_id, 'folded'] = folded
382
383 return 'Verification failed. Your hand has been forfeited.'
384
385 else:
386 cards = player_hand_str.split(':')[0].split(',')
387
388 game_id = hands[hand_id, 'game_id']
389 game_type = games[game_id, 'game_type']
390
391 if game_type == BLIND_POKER:
392 j = 0
393 for p in active_players:
394 if p != player:
395 if p not in folded:
396 card = cards[j]
397 rank = evaluator.evaluate([card])
398 if hands[hand_id, p, 'rank'] is None:
399 hands[hand_id, p, 'rank'] = rank
400 hands[hand_id, p, 'hand'] = card
401 j += 1
402 else:
403 if game_type == HOLDEM_POKER or game_type == OMAHA_POKER:
404 # Add community cards
405 community = hands[hand_id, 'community']
406 assert community is not None, 'Please reveal the community cards first.'
407 assert community[0] is not None and community[1] is not None and community[2] is not None, 'Please reveal all community cards.'
408 cards.extend(community[0].split(','))
409 cards.extend(community[1:])
410 rank = evaluator.evaluate(cards)
411 hands[hand_id, player, 'rank'] = rank
412 hands[hand_id, player, 'hand'] = cards
413
414 return 'Verification succeeded.'
415
416
417 def calculate_ranks(hand_id: str, players: list, hands: Any) -> dict:
418 ranks = {}
419 for p in players:
420 rank = hands[hand_id, p, 'rank']
421 assert rank is not None, f'Player {p} has not verified their hand yet.'
422 if rank not in ranks:
423 ranks[rank] = []
424 ranks[rank].append(p)
425 return ranks
426
427
428 @export
429 def payout_hand(hand_id: str, games: Any, hands: Any):
430 pot = hands[hand_id, 'pot']
431 assert pot > 0, 'There is no pot to claim!'
432 assert not hands[hand_id, 'payed_out'], 'This hand has already been payed out.'
433
434 folded = hands[hand_id, 'folded']
435 all_in = hands[hand_id, 'all_in']
436 active_players = hands[hand_id, 'active_players']
437
438 remaining = [p for p in active_players if p not in folded]
439 assert len(remaining) > 0, 'There are no remaining players.'
440
441 payouts = {}
442
443 if len(remaining) == 1:
444 # Just pay out, everyone else folded
445 payouts[remaining[0]] = pot
446 else:
447 ranks = calculate_ranks(hand_id, remaining, hands)
448 if len(all_in) > 0:
449 # Need to calculate split pots
450 all_in_map = {}
451 for player in all_in:
452 # Check all in amount
453 amount = hands[hand_id, player, 'max_bet']
454 all_in_map[player] = amount
455 all_pots = sorted(all_in_map.values())
456 unique_pots = []
457 for bet in all_pots:
458 if bet not in unique_pots:
459 unique_pots.append(bet)
460 total_payed_out = 0
461 previous_pot_payout = 0
462 for bet in unique_pots:
463 players_in_pot = []
464 for player in remaining:
465 if player not in all_in_map or all_in_map[player] >= bet:
466 players_in_pot.append(player)
467 pot_winners = evaluator.find_winners(ranks, players_in_pot)
468 pot_payout = (bet * len(players_in_pot)) - previous_pot_payout
469 total_payed_out += pot_payout
470 payout = pot_payout / len(pot_winners)
471 for winner in pot_winners:
472 if winner not in payouts:
473 payouts[winner] = 0
474 payouts[winner] += payout
475 previous_pot_payout += pot_payout
476
477 remaining_to_payout = pot - total_payed_out
478 not_all_in = set(remaining).difference(set(all_in))
479 assert remaining_to_payout >= 0, 'Invalid remaining to payout.'
480 assert remaining_to_payout == 0 or len(not_all_in) > 0, 'Invalid state when calculating side pots.'
481 if remaining_to_payout > 0:
482 if len(not_all_in) == 1:
483 winners = not_all_in
484 else:
485 winners = evaluator.find_winners(ranks, not_all_in)
486 payout = remaining_to_payout / len(winners)
487 for winner in winners:
488 if winner not in payouts:
489 payouts[winner] = 0
490 payouts[winner] += payout
491 else:
492 winners = evaluator.find_winners(ranks, remaining)
493 payout = pot / len(winners)
494 for winner in winners:
495 payouts[winner] = payout
496
497 game_id = hands[hand_id, 'game_id']
498 for player, payout in payouts.items():
499 games[game_id, player] += payout
500
501 hands[hand_id, 'winners'] = list(payouts.keys())
502 hands[hand_id, 'payouts'] = payouts
503 hands[hand_id, 'payed_out'] = True
504
505
506 @export
507 def leave_hand(hand_id: str, player: str, hands: Any):
508 active_players = hands[hand_id, 'active_players'] or []
509 if player in active_players:
510 folded = hands[hand_id, 'folded']
511 all_in = hands[hand_id, 'all_in']
512 next_better = hands[hand_id, 'next_better']
513 if next_better == player:
514 next_better = evaluator.get_next_better(active_players, folded, all_in, player)
515 hands[hand_id, 'next_better'] = next_better
516 active_players.remove(player)
517 hands[hand_id, 'active_players'] = active_players
518 if player in folded:
519 folded.remove(player)
520 hands[hand_id, 'folded'] = folded
521 if player in all_in:
522 all_in.remove(player)
523 hands[hand_id, 'all_in'] = all_in

Byte Code

e30000000000000000000000000a0000004000000073ba010000640064016c005a01640064016c025a03640064016c045a0565066a078300010064005a0864025a0964035a0a64045a0b64055a0c64065a0d64005a0e64025a0f64025a1064035a1164045a1265136514651564079c036408640984045a1665176518640a9c02640b640c84045a1965136513640d9c02640e640f84045a1a651b641083016513651365146514651364119c0564126413840483015a1c651b64108301651365136514651464149c0464156416840483015a1d651b641083016513651365146514651464179c0564186419840483015a1e651365186513651765176517651365146513641a9c09641b641c84045a1f651b6410830165136520651365146514641d9c05641e641f840483015a21651b6410830165136518651865186513651464209c0664216422840483015a22651b64108301651365186514651364239c0464246425840483015a23651b6410830165136513651365146514651364269c0664276428840483015a24651365176514651564299c04642a642b84045a25651b64108301651365146514642c9c03642d642e840483015a26651b64108301651365136514642f9c0364306431840483015a27640153002932e9000000004ee901000000e902000000e903000000e90400000069ffe0f5052903da0767616d655f6964da0567616d6573da0672657475726e63020000000000000003000000040000004300000073280000007c017c006401660219007d027c0264006b097324740064027c009b0064039d03830182017c02530029044eda07706c61796572737a0547616d65207a1020646f6573206e6f742065786973742e2901da0e417373657274696f6e4572726f722903720600000072070000007209000000a900720b000000da00da1f5f5f6765745f706c61796572735f616e645f6173736572745f65786973747312000000730600000000010c011801720d0000002902720900000072080000006301000000000000000200000003000000030000007310000000870066016401640284087d017c01530029034e630100000000000000010000000200000013000000730a00000088006a007c008301530029014e2901da05696e6465782901da06706c6179657229017209000000720b000000720c000000da065f5f736f72741a000000730200000000017a245f5f6163746976655f706c617965725f736f72742e3c6c6f63616c733e2e5f5f736f7274720b000000290272090000007210000000720b00000029017209000000720c000000da145f5f6163746976655f706c617965725f736f727418000000730400000000020c0272110000002902da046e616d657208000000630100000000000000010000000500000043000000731800000074006a0164016a027c00740374048301670283018301530029024efa013a2905da07686173686c6962da0473686133da046a6f696eda03737472da036e6f7729017212000000720b000000720b000000720c000000da105f5f6372656174655f68616e645f69641f000000730200000000017219000000da1c636f6e5f706f6b65725f68616e645f636f6e74726f6c6c65725f763129057206000000da066465616c65727207000000da0568616e6473720800000063040000000000000007000000040000004300000073e800000074007c007c0283027d047c017c046b06731a740164018301820174027c04830164026b04732e74016403830182017c027c006404660219007d057c0564006b0972567c037c056405660219007356740164068301820174037c0064078d017d067c067c027c00640466023c007c007c037c06640866023c007c017c037c06640966023c0067007c037c06640a66023c00640b7c037c06640c66023c00640b7c037c06640566023c00640b7c037c06640d66023c0067007c037c06640e66023c00640f7c037c06641066023c00640f7c037c06641166023c0067007c037c06641266023c007c06530029134e7a20596f7520617265206e6f7420612070617274206f6620746869732067616d652e72020000007a24596f752063616e6e6f7420737461727420612068616e6420627920796f757273656c662eda0c63757272656e745f68616e64da0970617965645f6f75747a2d5468652070726576696f75732068616e6420686173206e6f74206265656e207061796564206f7574207965742e290172120000007206000000721b000000da06666f6c64656446da09636f6d706c65746564da0e726561636865645f6465616c6572da0e6163746976655f706c61796572737201000000da0b63757272656e745f626574da03706f74da06616c6c5f696e2904720d000000720a000000da036c656e721900000029077206000000721b0000007207000000721c0000007209000000da1070726576696f75735f68616e645f6964da0768616e645f6964720b000000720b000000720c000000da0a73746172745f68616e6423000000732800000000020a01100114010c0108010e0106010a010c010c010c010c010c010c010c010c010c010c010c01722900000029047228000000720f0000007207000000721c0000006304000000000000000c0000000500000043000000738e0100007c037c006401660219007d047c0464006b09731c740064028301820174017c047c0283027d057c017c056b06733674006403830182017c027c046404660219007d067c027c047c01660219007d077c0764006b09725e7c077c066b05736674006405830182017c037c00640666021900707467007d087c017c086b07738674006407830182017c027c046408660219007d097c0974026b0272ac64097c027c04640a660219001a007d0a6e207c0974036b0272ba640b7d0a6e127c0974046b0272c8640b7d0a6e04640c7d0a74057c0883017c0a6b0073e87400640d7c0a9b00640e9d03830182017c067c037c007c01640f66033c007c077c037c007c01641066033c007c027c047c016602050019007c06380003003c007c086a067c01830101007c086a0774087c05830164118d0101007c087c037c00640666023c007c067c037c00641266023c007c037c0064136602050019007c06370003003c007c077c066b029001728a7c037c006414660219007d0b7c0b6a067c01830101007c0b7c037c00641466023c006400530029154e72060000007a19546869732067616d6520646f6573206e6f742065786973742e7a20596f7520617265206e6f7420612070617274206f6620746869732067616d652eda04616e74657a1d596f7520646f206e6f74206861766520656e6f7567682063686970732e72220000007a1f596f75206861766520616c726561647920706169642074686520616e74652eda0967616d655f74797065e934000000da0d6e5f63617264735f746f74616ce90a000000e9320000007a0d41206d6178696d756d206f66207a1f20697320616c6c6f77656420666f7220746869732067616d6520747970652eda03626574da076d61785f6265742901da036b65797223000000722400000072250000002909720a000000720d000000da0a535455445f504f4b4552da0c484f4c44454d5f504f4b4552da0b4f4d4148415f504f4b45527226000000da06617070656e64da04736f72747211000000290c7228000000720f0000007207000000721c00000072060000007209000000722a000000da0563686970737222000000722b000000da0b6d61785f706c61796572737225000000720b000000720b000000720c000000da07616e74655f75703b000000733e00000000020c0110010a0110010c010c011801100110010c010801120108010601080106020401060116010e010e0114010a0110010c010c0114010a010c010a01723a00000029057228000000721b0000007207000000721c000000da0f706c617965725f6d6574616461746163050000000000000024000000070000004300000073300500007c037c006401660219007d057c017c037c006402660219006b027324740064038301820174017c05830164046b0473447400640574017c0583019b0064069d03830182017c017c056b06735474006407830182017c037c006408660219007d067c027c066409660219007d0774026a0383007d087c027c06640a660219007d097c027c06640b660219007d0a7c0774046b02739c7c0774056b0272be640c6a067c08640d640e8502190083017c08640e19007c08640f190067037d0b6e0464007d0b9004781a740774017c0583018301440090045d087d0c7c057c0c19007d0d7c047c0d6410660219007d0e7c0e64006b0990017306740064117c0d9b0064129d03830182017c0e6a08641383017d0f74017c0f830164146b029001732674006415830182017c0774096b02900172447c087c0c7c0c64041700850219007d1090016e027c07740a6b02900172a67c08640d7c0c850219007c087c0c6404170074017c0583018502190017007d1074017c10830174017c058301640418006b02900273467400641674017c1083019b00641774017c058301640418009b009d04830182016ea07c07740b6b02900172e07c087c097c0c14007c097c0c14007c091700850219007d1074017c1083017c096b029002734674006418830182016e667c0774046b029002720c7c08641964147c0c14001700641964147c0c1400170064141700850219007d106e3a7c0774056b02900272387c086419640f7c0c140017006419640f7c0c14001700640f1700850219007d106e0e641a900273467400641b83018201640c6a067c1083017d117c0a64006b09900272787c0a7c096b0090027278640c6a067c107c0a64008502190083017d126e0464007d12740c740d6a0e640d740f830283017d137c0b64006b099004727074106a11641c83017d1474106a11641d83017d1574106a11641d83017d16740c740d6a0e640d740f830283017d17740c740d6a0e640d740f830283017d18740c740d6a0e640d740f830283017d197c0c640d6b029003723874106a127c0b640d19007c14641a641e8d037c0b640d3c0074106a127c0b640419007c15641a641e8d037c0b64043c0074106a127c0b641419007c16641a641e8d037c0b64143c006e4874106a137c0b640d19007c14641a641e8d037c0b640d3c0074106a137c0b640419007c15641a641e8d037c0b64043c0074106a137c0b641419007c16641a641e8d037c0b64143c007c149b00641f7c179b009d037d1a7c159b00641f7c189b009d037d1b7c169b00641f7c199b009d037d1c74146a127c1a74157c0f640d1900830174157c0f64041900830164208d037d1d74146a127c1b74157c0f640d1900830174157c0f64041900830164208d037d1e74146a127c1c74157c0f640d1900830174157c0f64041900830164208d037d1f7c1d7c037c007c0d642166033c007c1e7c037c007c0d642266033c007c1f7c037c007c0d642366033c0074166a177c1a83017c037c007c0d642466033c0074166a177c1b83017c037c007c0d642566033c0074166a177c1c83017c037c007c0d642666033c007c119b00641f7c139b009d037d2074146a127c2074157c0f640d1900830174157c0f64041900830164208d037d2174166a177c2083017d227c1264006b09900472c07c127c037c007c0d642766033c007c217c037c007c0d642866033c007c227c037c007c0d642966033c0071d257007c037c00642a660219007d2374026a187c0567007c237c0183047c037c00642b66023c007c0b64006b099005722c7c0b7c037c00642c66023c0064006400640067037c037c00642d66023c0064005300292e4e7222000000721b0000007a17596f7520617265206e6f7420746865206465616c65722e72020000007a1b4e6f7420656e6f7567682061637469766520706c61796572733a207a05203c3d20317a27596f7520617265206e6f74206163746976656c792070617274206f6620746869732068616e642e7206000000722b000000722d000000da0c6e5f686f6c655f6361726473fa012c720100000072040000007205000000da0e7075626c69635f7273615f6b65797a07506c61796572207a2520686173206e6f7420736574757020746865697220656e6372797074696f6e206b6579732efa017c72030000007a0c496e76616c6964206b6579737a16536f6d657468696e672077656e742077726f6e672e207a0420213d207a15536f6d657468696e672077656e742077726f6e672ee905000000467a12496e76616c69642067616d6520747970652ee950000000e9140000002901da047361666572130000002903da0b6d6573736167655f737472da016eda0165da15706c617965725f656e637279707465645f70616431da15706c617965725f656e637279707465645f70616432da15706c617965725f656e637279707465645f70616433da14686f7573655f656e637279707465645f70616431da14686f7573655f656e637279707465645f70616432da14686f7573655f656e637279707465645f70616433da0b7075626c69635f68616e64da15706c617965725f656e637279707465645f68616e64da14686f7573655f656e637279707465645f68616e647225000000da0b6e6578745f626574746572da13636f6d6d756e6974795f656e63727970746564da09636f6d6d756e6974792919720a0000007226000000da096576616c7561746f72da086765745f6465636b723400000072350000007216000000da0572616e6765da0573706c6974da0e4f4e455f434152445f504f4b4552da0b424c494e445f504f4b455272330000007217000000da0672616e646f6dda0772616e64696e74da114d41585f52414e444f4d5f4e554d424552da036f7470da0c67656e65726174655f6f7470da07656e6372797074da0b656e63727970745f686578da03727361da03696e7472140000007215000000da0f6765745f6e6578745f62657474657229247228000000721b0000007207000000721c000000723b00000072220000007206000000722b000000da056361726473722d000000723c000000da0f636f6d6d756e6974795f6361726473da0169720f000000da0a706c617965725f6b6579da046b657973da0b706c617965725f68616e64da0f706c617965725f68616e645f737472da0f7075626c69635f68616e645f737472da0473616c74da0470616431da0470616432da0470616433da0573616c7431da0573616c7432da0573616c7433da0e706164315f776974685f73616c74da0e706164325f776974685f73616c74da0e706164335f776974685f73616c74da0e656e637279707465645f70616431da0e656e637279707465645f70616432da0e656e637279707465645f70616433da19706c617965725f68616e645f7374725f776974685f73616c74724e000000724f0000007225000000720b000000720b000000720c000000da0a6465616c5f63617264735f00000073b600000000030c01180106011a0110010c010c0108010c010c01100122020401160108010c011a010a0116010a0114010a0120010c012c010a010e010a0118010a0122010a0122020e010a0114011402040110010a010a010a010a011001100110010a010c010c010c010c010c010e020a010e010a010e010a010e010e010e010e010801180108011801080118010e010e010e010401100104011001040110010e0104011c010a010a010e010e0112010c01060112010a010c01727900000029097228000000722b00000072500000007222000000721f0000007225000000721b000000721c000000720800000063080000000000000009000000050000004300000073840000007c0174006b0273107c0174016b0272747c077c00640166021900701e64027d087c08640337007d087c087c077c00640166023c007c0864046b02724a64057c077c00640666023c00718064077c077c00640866023c0074026a037c037c047c057c0683047d027c027c077c00640966023c006e0c64057c077c00640666023c007c025300290a4eda05726f756e6472010000007202000000720500000054722000000046da0b66756c6c5f636972636c65da0c66697273745f6265747465722904723400000072350000007253000000726200000029097228000000722b00000072500000007222000000721f0000007225000000721b000000721c000000727a000000720b000000720b000000720c000000da155f5f68616e646c655f646f6e655f62657474696e67c3000000731800000000031001100108010c0108010e020c01080108010e020c01727d000000290572280000007230000000720f0000007207000000721c000000630500000000000000150000000900000043000000730e0300007c047c007c0264016603190064006b09731a74006402830182017c047c006403660219000c00733074006404830182017c047c006405660219007c026b02734874006406830182017c047c006407660219007d057c047c006408660219007d067c047c006409660219007d077c076a0183007d087c047c00640a660219007082640b7d097c047c007c02640c660319007094640b7d0a7c047c00640d660219007d0b74026a037c057c067c077c0283047d0c7c0b7c026b0273d27c0c64006b0972e47c0c7c047c00640e660219006b0272e4640f7c047c00641066023c00640f7d0d6e0c7c047c006410660219007d0d7c0c64006b089001720a640f7c047c00640366023c0090016ef47c047c006411660219007d0e7c037c0e6412660219007d0f7c047c007c0c640c660319007d107c01640b6b009001729a7c066a047c02830101007c067c047c00640866023c007c027c076b06900172707c076a057c02830101007c077c047c00640966023c0074067c06830174067c058301641318006b0290017292640f7c047c00640366023c007c097d1190016e347c01640b6b02900172e27c047c007c026414660319007d127c127c0a6b02900172dc7c027c076b07900172dc7c076a047c02830101007c077c047c00640966023c007c0a7d116ed07c037c0e7c02660219007c016b05900173fc74006415830182017c037c0e6416660219007d137c1374076b02900272307c047c006417660219007d147c017c146b019002733074006418830182017c0a7c0117007d117c047c007c026414660319007d127c127c116b02900272707c027c076b07900272707c076a047c02830101007c077c047c00640966023c007c117c047c007c02640c66033c007c117c047c00640a66023c007c047c0064176602050019007c01370003003c007c037c0e7c026602050019007c01380003003c007c127c116b02900273ce7c117c096b05900273ce74006419830182017c1064006b09900272fe7c107c116b02900272fe7c0d900272fe74087c007c0f7c0c7c057c067c087c0b7c0483087d0c7c0c7c047c00640566023c0064005300291a4e724e0000007a1348616e6420646f6573206e6f7420657869737472200000007a20546869732068616e642068617320616c726561647920636f6d706c657465642e72500000007a1b4974206973206e6f7420796f7572207475726e20746f206265742e7222000000721f0000007225000000722300000072010000007230000000721b000000727c00000054727b0000007206000000722b000000720200000072310000007a2d596f7520646f206e6f74206861766520656e6f75676820636869707320746f206d616b65207468697320626574da086265745f7479706572240000007a2943616e6e6f74206f7665726265742074686520706f7420696e20706f742d6c696d6974206d6f64652e7a3843757272656e74206265742069732061626f766520796f75722062657420616e6420796f7520646964206e6f7420676f20616c6c20696e2e2909720a000000da04636f7079725300000072620000007236000000da0672656d6f76657226000000da09504f545f4c494d4954727d000000291572280000007230000000720f0000007207000000721c0000007222000000721f0000007225000000da0b6f7269675f616c6c5f696eda0863616c6c5f626574da13706c617965725f70726576696f75735f626574721b0000007250000000727b0000007206000000722b000000da106e6578745f706c61796572735f62657472230000007231000000727e0000007224000000720b000000720b000000720c000000da116265745f636865636b5f6f725f666f6c64d6000000737800000000030c010e0116010a010e010c010c010c010801100112010c010a01060114010c010c0106020c010a0110020c010c010e010a010a010c010a010a010c0116010c0108020a010e0114010a010c0106020a0110010c010a010c01120108010e0114010a010c010e010c01140114011c010c010e0106011002728600000029067228000000da03706164726b000000720e000000720f000000721c00000063060000000000000008000000060000004300000073940000007c0374007401740266036b06731674036401830182017c057c006402660219007d067c0664006b09733274036403830182017c066a047c0483017d077c0764046b05734c740364058301820174056a067c019b0064067c029b009d0383017c057c007c0464077c039b009d02660319006b02737c74036408830182017c017c057c007c0464097c039b009d0266033c0064005300290a4e7a0e496e76616c696420696e6465782e72220000007a19546869732068616e6420646f6573206e6f742065786973742e72010000007a19596f7520617265206e6f7420696e20746869732068616e642e7213000000da13686f7573655f656e637279707465645f7061647a14496e76616c6964206b6579206f722073616c742e72870000002907da04464c4f50da045455524eda055249564552720a000000720e00000072140000007215000000290872280000007287000000726b000000720e000000720f000000721c0000007222000000da0c706c617965725f696e646578720b000000720b000000720c000000da0a72657665616c5f6f74701c0100007310000000000316010c0110010a01100118011801728d00000029047228000000720e000000721c00000072080000006303000000000000000a000000060000004300000073de0000007c0174007401740266036b06731674036401830182017c027c006402660219007d037c027c006403660219007d047c027c006404660219007c016405180019007d0574047c0383017d06787674057c06830144005d6a7d077c03640b7c07180019007d087c027c007c0864067c019b009d02660319007d097c0964006b097390740364077c089b0064089d03830182017c077c06640518006b0372ae74066a077c057c096409640a8d037d05715474066a087c057c096409640a8d037d05715457007c057c047c01640518003c007c047c027c00640366023c007c055300290c4e7a0e496e76616c696420696e6465782e722200000072520000007251000000720200000072870000007a07506c61796572207a1c20686173206e6f742072657665616c6564207468656972207061642e462903da0d656e637279707465645f737472725c0000007243000000e9ffffffff29097289000000728a000000728b000000720a00000072260000007255000000725c000000da0b646563727970745f686578da0764656372797074290a7228000000720e000000721c00000072220000007252000000da03656e63da096e5f706c61796572737265000000720f0000007287000000720b000000720b000000720c000000da0672657665616c29010000731e000000000216010c010c01140108010e010c01140118010c01120214010c010c017294000000290672280000007269000000720f0000007207000000721c000000720800000063050000000000000014000000060000004300000073500200007c047c00640166021900731474006402830182017c047c006403660219007d057c027c056b07733074006404830182017c047c006405660219007d067c027c066b06734c74006406830182017c047c006407660219007d077c0764006b09736874006408830182017c047c007c026409660319007d087c0864006b0973867400640a830182017c077c086b0273a67c027c047c00640b660219006b0673a67400640c8301820174016a027c0183017d097c047c007c02640d660319007d0a7c0a64006b096fcc7c0a7c096b027d0b7c0b73ec7c056a037c02830101007c057c047c00640366023c00640e53007c016a04640f8301641019006a04641183017d0c7c047c006412660219007d0d7c037c0d6413660219007d0e7c0e74056b029001729864107d0f786e7c0644005d667d107c107c026b039001722c7c107c056b07900172887c0c7c0f19007d1174066a077c11670183017d127c047c007c1064146603190064006b08900172887c127c047c007c10641466033c007c117c047c007c10641566033c007c0f641637007d0f9001712c57006eb07c0e74086b02900173ac7c0e74096b02900272227c047c006417660219007d137c1364006b09900173ca74006418830182017c136410190064006b09900172f47c136416190064006b09900172f47c136419190064006b09900173fc7400641a830182017c0c6a0a7c13641019006a0464118301830101007c0c6a0a7c1364166400850219008301010074066a077c0c83017d127c127c047c007c02641466033c007c0c7c047c007c02641566033c00641b530064005300291c4e72200000007a20546869732068616e6420686173206e6f7420636f6d706c65746564207965742e721f0000007a2f4e6f206e65656420746f2076657269667920796f75722068616e64206265636175736520796f7520666f6c6465642e72220000007a2a596f7520617265206e6f7420616e2061637469766520706c6179657220696e20746869732068616e642e72230000007a185468657265206973206e6f2063757272656e74206265742e72300000007a15596f752068617665206e6f7420626574207965742e72250000007a19426574732068617665206e6f742073746162696c697a65642e724f0000007a32566572696669636174696f6e206661696c65642e20596f75722068616e6420686173206265656e20666f726665697465642e72130000007201000000723d0000007206000000722b000000da0472616e6bda0468616e64720200000072520000007a28506c656173652072657665616c2074686520636f6d6d756e6974792063617264732066697273742e72030000007a22506c656173652072657665616c20616c6c20636f6d6d756e6974792063617264732e7a17566572696669636174696f6e207375636365656465642e290b720a000000721400000072150000007236000000725600000072580000007253000000da086576616c7561746572340000007235000000da06657874656e64291472280000007269000000720f0000007207000000721c000000721f0000007222000000da106265745f73686f756c645f657175616cda0a706c617965725f626574724f000000da1d70726576696f75735f686f7573655f656e637279707465645f68616e64da08766572696669656472630000007206000000722b000000da016ada0170da046361726472950000007252000000720b000000720b000000720c000000da0b7665726966795f68616e643d010000735c000000000314010c0110010c0110010c0110010e0110011a0106010a01060108010801080104010a010c01040214010c010c010a0104010a010a010a0108010c0114010e010e01100214010c01120114010e011001140112010a010e010e0172a0000000290472280000007209000000721c0000007208000000630300000000000000060000000500000043000000735a00000069007d0378507c0144005d487d047c027c007c046401660319007d057c0564006b097334740064027c049b0064039d03830182017c057c036b07724467007c037c053c007c037c0519006a017c0483010100710a57007c03530029044e72950000007a07506c61796572207a2120686173206e6f742076657269666965642074686569722068616e64207965742e2902720a0000007236000000290672280000007209000000721c000000da0572616e6b73729e0000007295000000720b000000720b000000720c000000da115f5f63616c63756c6174655f72616e6b73720100007310000000000104010a010e01180108010801120172a2000000290372280000007207000000721c0000006303000000000000001a000000060000000300000073140300007c027c006401660219007d037c0364026b04731c74006403830182017c027c006404660219000c00733274006405830182017c027c0064066602190089007c027c006407660219007d047c027c006408660219007d05870066016409640a84087c05440083017d0674017c06830164026b04737c7400640b8301820169007d0774017c068301640c6b02729c7c037c077c06640219003c0090026e1074027c007c067c0283037d0874017c04830164026b049002727c69007d0978227c0444005d1a7d0a7c027c007c0a640d660319007d0b7c0b7c097c0a3c0071c0570074037c096a04830083017d0c67007d0d781e7c0c44005d167d0e7c0e7c0d6b0772f47c0d6a057c0e8301010071f4570064027d0f64027d1078ae7c0d44005da67d0e67007d1178307c0644005d287d0a7c0a7c096b07900173467c097c0a19007c0e6b059001722a7c116a057c0a830101009001712a570074066a077c087c1183027d127c0e74017c11830114007c1018007d137c0f7c1337007d0f7c1374017c1283011b007d1478307c1244005d287d157c157c076b07900172a264027c077c153c007c077c15050019007c14370003003c009001718c57007c107c1337007d109001711c57007c037c0f18007d1674087c0683016a0974087c04830183017d177c1664026b05900173f27400640e830182017c1664026b029002731274017c17830164026b04900273127400640f830182017c1664026b04900272ac74017c178301640c6b02900272307c177d186e0c74066a077c087c1783027d187c1674017c1883011b007d1478627c1844005d287d157c157c076b079002726464027c077c153c007c077c15050019007c14370003003c009002714e57006e3074066a077c087c0683027d187c0374017c1883011b007d1478167c1844005d0e7d157c147c077c153c009002719a57007c027c006410660219007d19782a7c076a0a830044005d1e5c027d0a7d147c017c197c0a6602050019007c14370003003c00900271c25700740b7c076a0c830083017c027c00641166023c007c077c027c00641266023c0064137c027c00640466023c006400530029144e722400000072010000007a195468657265206973206e6f20706f7420746f20636c61696d21721e0000007a25546869732068616e642068617320616c7265616479206265656e207061796564206f75742e721f00000072250000007222000000630100000000000000020000000400000013000000731800000067007c005d107d017c0188006b0772047c01910271045300720b000000720b0000002902da022e30729e0000002901721f000000720b000000720c000000fa0a3c6c697374636f6d703e86010000730200000006007a1f7061796f75745f68616e642e3c6c6f63616c733e2e3c6c697374636f6d703e7a1f546865726520617265206e6f2072656d61696e696e6720706c61796572732e720200000072310000007a1c496e76616c69642072656d61696e696e6720746f207061796f75742e7a29496e76616c6964207374617465207768656e2063616c63756c6174696e67207369646520706f74732e7206000000da0777696e6e657273da077061796f75747354290d720a000000722600000072a2000000da06736f72746564da0676616c75657372360000007253000000da0c66696e645f77696e6e657273da03736574da0a646966666572656e6365da056974656d73da046c6973747267000000291a72280000007207000000721c000000722400000072250000007222000000da0972656d61696e696e6772a600000072a1000000da0a616c6c5f696e5f6d6170720f000000da06616d6f756e74da08616c6c5f706f7473da0b756e697175655f706f74737230000000da0f746f74616c5f70617965645f6f7574da1370726576696f75735f706f745f7061796f7574da0e706c61796572735f696e5f706f74da0b706f745f77696e6e657273da0a706f745f7061796f7574da067061796f7574da0677696e6e6572da1372656d61696e696e675f746f5f7061796f7574da0a6e6f745f616c6c5f696e72a50000007206000000720b0000002901721f000000720c000000da0b7061796f75745f68616e647d010000737e00000000020c011001100106010c010c010c011201140104010c0110020c010e0104010a010e010c010c0104010a0108010e01040104010a0104010a01180110010c01100108010c010a010a01080116010e01080112011201100110010a010e0106020c010c010a010a01080118020c010c010a010e010c0112011a0114010c0172bc00000029037228000000720f000000721c00000063030000000000000007000000050000004300000073b60000007c027c00640166021900700e67007d037c017c036b0672b27c027c006402660219007d047c027c006403660219007d057c027c006404660219007d067c067c016b02726074006a017c037c047c057c0183047d067c067c027c00640466023c007c036a027c01830101007c037c027c00640166023c007c017c046b0672947c046a027c01830101007c047c027c00640266023c007c017c056b0672b27c056a027c01830101007c057c027c00640366023c006400530029054e7222000000721f00000072250000007250000000290372530000007262000000728000000029077228000000720f000000721c0000007222000000721f00000072250000007250000000720b000000720b000000720c000000da0a6c656176655f68616e64c301000073220000000002100108010c010c010c010801080108010c010a010c0108010a010c0108010a0172bd0000002928da12636f6e5f7273615f656e6372797074696f6e7260000000da0a636f6e5f6f74705f7631725c000000da15636f6e5f68616e645f6576616c7561746f725f763172530000007259000000da047365656472570000007258000000723300000072340000007235000000725b000000da084e4f5f4c494d495472810000007289000000728a000000728b0000007217000000da03416e79da0464696374720d00000072ad000000726100000072110000007219000000da085f5f6578706f72747229000000723a0000007279000000727d000000da05666c6f61747286000000728d000000729400000072a000000072a200000072bc00000072bd000000720b000000720b000000720b000000720c000000da083c6d6f64756c653e010000007356000000080108010801080104010401040104010401040104010401040104010403120610071004060118170601162306010801106206010a010e1106010801104406010a01100b06011613060108011233140b060114450601