Contract con_poker_hand_controller_v3


Contract Code

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

Byte Code

e30000000000000000000000000a000000400000007310020000640064016c005a01640064016c025a03640064016c045a0565066a078300010064005a0864025a0964035a0a64045a0b64055a0c64065a0d64005a0e64025a0f64025a1064035a1164045a1265136514651564079c036408640984045a1665176518640a9c02640b640c84045a1965136513640d9c02640e640f84045a1a651b641083016513651365146514651364119c0564126413840483015a1c651b64108301651365136514651464149c0464156416840483015a1d651b641083016513651365146514651464179c0564186419840483015a1e651565176517641a9c03641b641c84045a1f65176517651765136513641d9c05641e641f84045a2065136518651365176517651765136514651364209c096421642284045a21651365136514652264239c046424642584045a23651b641083016513652465136514651464269c0564276428840483015a25651b6410830165136518651865186513651464299c06642a642b840483015a26651b641083016513651865146513642c9c04642d642e840483015a27651b64108301651365136513651465146513642f9c0664306431840483015a28651365176514651564329c046433643484045a29651b6410830165136514651464359c0364366437840483015a2a651b6410830165136513651365226514651464389c066439643a840483015a2b6513651365146514643b9c04643c643d84045a2c64015300293ee9000000004ee901000000e902000000e903000000e90400000069ffe0f5052903da0767616d655f6964da0567616d6573da0672657475726e63020000000000000003000000040000004300000073280000007c017c006401660219007d027c0264006b097324740064027c009b0064039d03830182017c02530029044eda07706c61796572737a0547616d65207a1020646f6573206e6f742065786973742e2901da0e417373657274696f6e4572726f722903720600000072070000007209000000a900720b000000da00da1f5f5f6765745f706c61796572735f616e645f6173736572745f65786973747312000000730600000000010c011801720d0000002902720900000072080000006301000000000000000200000003000000030000007310000000870066016401640284087d017c01530029034e630100000000000000010000000200000013000000730a00000088006a007c008301530029014e2901da05696e6465782901da06706c6179657229017209000000720b000000720c000000da065f5f736f72741a000000730200000000017a245f5f6163746976655f706c617965725f736f72742e3c6c6f63616c733e2e5f5f736f7274720b000000290272090000007210000000720b00000029017209000000720c000000da145f5f6163746976655f706c617965725f736f727418000000730400000000020c0272110000002902da046e616d657208000000630100000000000000010000000500000043000000731800000074006a0164016a027c00740374048301670283018301530029024efa013a2905da07686173686c6962da0473686133da046a6f696eda03737472da036e6f7729017212000000720b000000720b000000720c000000da105f5f6372656174655f68616e645f69641f000000730200000000017219000000da1c636f6e5f706f6b65725f68616e645f636f6e74726f6c6c65725f763329057206000000da066465616c65727207000000da0568616e6473720800000063040000000000000007000000040000004300000073f400000074007c007c0283027d047c017c046b06731a740164018301820174027c04830164026b04732e74016403830182017c027c006404660219007d057c0564006b0972567c037c056405660219007356740164068301820174037c0064078d017d067c067c027c00640466023c007c057c037c06640866023c007c007c037c06640966023c007c017c037c06640a66023c0067007c037c06640b66023c00640c7c037c06640d66023c00640c7c037c06640566023c00640c7c037c06640e66023c0067007c037c06640f66023c0064107c037c06641166023c0064107c037c06641266023c0067007c037c06641366023c007c06530029144e7a20596f7520617265206e6f7420612070617274206f6620746869732067616d652e72020000007a24596f752063616e6e6f7420737461727420612068616e6420627920796f757273656c662eda0c63757272656e745f68616e64da0970617965645f6f75747a2d5468652070726576696f75732068616e6420686173206e6f74206265656e207061796564206f7574207965742e29017212000000da1070726576696f75735f68616e645f69647206000000721b000000da06666f6c64656446da09636f6d706c65746564da0e726561636865645f6465616c6572da0e6163746976655f706c61796572737201000000da0b63757272656e745f626574da03706f74da06616c6c5f696e2904720d000000720a000000da036c656e721900000029077206000000721b0000007207000000721c0000007209000000721f000000da0768616e645f6964720b000000720b000000720c000000da0a73746172745f68616e6423000000732a00000000020a01100114010c0108010e0106010a010c010c010c010c010c010c010c010c010c010c010c010c01722900000029047228000000720f0000007207000000721c0000006304000000000000000c0000000500000043000000738e0100007c037c006401660219007d047c0464006b09731c740064028301820174017c047c0283027d057c017c056b06733674006403830182017c027c046404660219007d067c027c047c01660219007d077c0764006b09725e7c077c066b05736674006405830182017c037c00640666021900707467007d087c017c086b07738674006407830182017c027c046408660219007d097c0974026b0272ac64097c027c04640a660219001a007d0a6e207c0974036b0272ba640b7d0a6e127c0974046b0272c8640b7d0a6e04640c7d0a74057c0883017c0a6b0073e87400640d7c0a9b00640e9d03830182017c067c037c007c01640f66033c007c077c037c007c01641066033c007c027c047c016602050019007c06380003003c007c086a067c01830101007c086a0774087c05830164118d0101007c087c037c00640666023c007c067c037c00641266023c007c037c0064136602050019007c06370003003c007c077c066b029001728a7c037c006414660219007d0b7c0b6a067c01830101007c0b7c037c00641466023c006400530029154e72060000007a19546869732067616d6520646f6573206e6f742065786973742e7a20596f7520617265206e6f7420612070617274206f6620746869732067616d652eda04616e74657a1d596f7520646f206e6f74206861766520656e6f7567682063686970732e72230000007a1f596f75206861766520616c726561647920706169642074686520616e74652eda0967616d655f74797065e934000000da0d6e5f63617264735f746f74616ce90a000000e9320000007a0d41206d6178696d756d206f66207a1f20697320616c6c6f77656420666f7220746869732067616d6520747970652eda03626574da076d61785f6265742901da036b65797224000000722500000072260000002909720a000000720d000000da0a535455445f504f4b4552da0c484f4c44454d5f504f4b4552da0b4f4d4148415f504f4b45527227000000da06617070656e64da04736f72747211000000290c7228000000720f0000007207000000721c00000072060000007209000000722a000000da0563686970737223000000722b000000da0b6d61785f706c61796572737226000000720b000000720b000000720c000000da07616e74655f75703c000000733e00000000020c0110010a0110010c010c011801100110010c010801120108010601080106020401060116010e010e0114010a0110010c010c0114010a010c010a01723a00000029057228000000721b0000007207000000721c000000da0f706c617965725f6d6574616461746163050000000000000028000000070000004300000073700500007c037c006401660219007d057c017c037c006402660219006b027324740064038301820174017c05830164046b0473447400640574017c0583019b0064069d03830182017c017c056b06735474006407830182017c037c006408660219007d067c027c066409660219007d0774026a0383007d087c027c06640a660219007d097c027c06640b660219007d0a7c0774046b02739c7c0774056b0272be640c6a067c08640d640e8502190083017c08640e19007c08640f190067037d0b6e0464007d0b9004781a740774017c0583018301440090045d087d0c7c057c0c19007d0d7c047c0d6410660219007d0e7c0e64006b0990017306740064117c0d9b0064129d03830182017c0e6a08641383017d0f74017c0f830164146b029001732674006415830182017c0774096b02900172447c087c0c7c0c64041700850219007d1090016e027c07740a6b02900172a67c08640d7c0c850219007c087c0c6404170074017c0583018502190017007d1074017c10830174017c058301640418006b02900273467400641674017c1083019b00641774017c058301640418009b009d04830182016ea07c07740b6b02900172e07c087c097c0c14007c097c0c14007c091700850219007d1074017c1083017c096b029002734674006418830182016e667c0774046b029002720c7c08641964147c0c14001700641964147c0c1400170064141700850219007d106e3a7c0774056b02900272387c086419640f7c0c140017006419640f7c0c14001700640f1700850219007d106e0e641a900273467400641b83018201640c6a067c1083017d117c0a64006b09900272787c0a7c096b0090027278640c6a067c107c0a64008502190083017d126e0464007d12740c740d6a0e640d740f830283017d137c0b64006b099004727074106a11641c83017d1474106a11641d83017d1574106a11641d83017d16740c740d6a0e640d740f830283017d17740c740d6a0e640d740f830283017d18740c740d6a0e640d740f830283017d197c0c640d6b029003723874106a127c0b640d19007c14641a641e8d037c0b640d3c0074106a127c0b640419007c15641a641e8d037c0b64043c0074106a127c0b641419007c16641a641e8d037c0b64143c006e4874106a137c0b640d19007c14641a641e8d037c0b640d3c0074106a137c0b640419007c15641a641e8d037c0b64043c0074106a137c0b641419007c16641a641e8d037c0b64143c007c149b00641f7c179b009d037d1a7c159b00641f7c189b009d037d1b7c169b00641f7c199b009d037d1c74146a127c1a74157c0f640d1900830174157c0f64041900830164208d037d1d74146a127c1b74157c0f640d1900830174157c0f64041900830164208d037d1e74146a127c1c74157c0f640d1900830174157c0f64041900830164208d037d1f7c1d7c037c007c0d642166033c007c1e7c037c007c0d642266033c007c1f7c037c007c0d642366033c0074166a177c1a83017c037c007c0d642466033c0074166a177c1b83017c037c007c0d642566033c0074166a177c1c83017c037c007c0d642666033c007c119b00641f7c139b009d037d2074146a127c2074157c0f640d1900830174157c0f64041900830164208d037d2174166a177c2083017d227c1264006b09900472c07c127c037c007c0d642766033c007c217c037c007c0d642866033c007c227c037c007c0d642966033c0071d257007c037c00642a660219007d237c056a187c0183017d247c246404170074017c05830116007d257c057c256400850219007c0564007c258502190017007d2674197c0567007c237c0183047d277c277c037c00642b66023c007c267c037c00640166023c007c0b64006b099005726c7c0b7c037c00642c66023c0064006400640067037c037c00642d66023c0064005300292e4e7223000000721b0000007a17596f7520617265206e6f7420746865206465616c65722e72020000007a1b4e6f7420656e6f7567682061637469766520706c61796572733a207a05203c3d20317a27596f7520617265206e6f74206163746976656c792070617274206f6620746869732068616e642e7206000000722b000000722d000000da0c6e5f686f6c655f6361726473fa012c720100000072040000007205000000da0e7075626c69635f7273615f6b65797a07506c61796572207a2520686173206e6f7420736574757020746865697220656e6372797074696f6e206b6579732efa017c72030000007a0c496e76616c6964206b6579737a16536f6d657468696e672077656e742077726f6e672e207a0420213d207a15536f6d657468696e672077656e742077726f6e672ee905000000467a12496e76616c69642067616d6520747970652ee950000000e9140000002901da047361666572130000002903da0b6d6573736167655f737472da016eda0165da15706c617965725f656e637279707465645f70616431da15706c617965725f656e637279707465645f70616432da15706c617965725f656e637279707465645f70616433da14686f7573655f656e637279707465645f70616431da14686f7573655f656e637279707465645f70616432da14686f7573655f656e637279707465645f70616433da0b7075626c69635f68616e64da15706c617965725f656e637279707465645f68616e64da14686f7573655f656e637279707465645f68616e647226000000da0b6e6578745f626574746572da13636f6d6d756e6974795f656e63727970746564da09636f6d6d756e697479291a720a0000007227000000da096576616c7561746f72da086765745f6465636b723400000072350000007216000000da0572616e6765da0573706c6974da0e4f4e455f434152445f504f4b4552da0b424c494e445f504f4b455272330000007217000000da0672616e646f6dda0772616e64696e74da114d41585f52414e444f4d5f4e554d424552da036f7470da0c67656e65726174655f6f7470da07656e6372797074da0b656e63727970745f686578da03727361da03696e7472140000007215000000720e000000da115f5f6765745f6e6578745f62657474657229287228000000721b0000007207000000721c000000723b00000072230000007206000000722b000000da056361726473722d000000723c000000da0f636f6d6d756e6974795f6361726473da0169720f000000da0a706c617965725f6b6579da046b657973da0b706c617965725f68616e64da0f706c617965725f68616e645f737472da0f7075626c69635f68616e645f737472da0473616c74da0470616431da0470616432da0470616433da0573616c7431da0573616c7432da0573616c7433da0e706164315f776974685f73616c74da0e706164325f776974685f73616c74da0e706164335f776974685f73616c74da0e656e637279707465645f70616431da0e656e637279707465645f70616432da0e656e637279707465645f70616433da19706c617965725f68616e645f7374725f776974685f73616c74724e000000724f0000007226000000da0c6465616c65725f696e6465787256000000da0f6f7264657265645f706c61796572737250000000720b000000720b000000720c000000da0a6465616c5f63617264736000000073be00000000030c01180106011a0110010c010c0108010c010c01100122020401160108010c011a010a0116010a0114010a0120010c012c010a010e010a0118010a0122010a0122020e010a0114011402040110010a010a010a010a011001100110010a010c010c010c010c010c010e020a010e010a010e010a010e010e010e010e010801180108011801080118010e010e010e010401100104011001040110010e0104011c010a010a010e010e0112010c010a01100118010e010c010c010a010c01727b0000002903da0572616e6b7372090000007208000000630200000000000000080000000400000043000000735600000074007c006a018300640164028d027d0274027c0183017d0378387c0244005d307d047c007c0419007d057c036a0374027c05830183017d0674047c06830164036b04721e74057c0683017d075000711e57007c07530029044e542901da077265766572736572010000002906da06736f727465647267000000da03736574da0c696e74657273656374696f6e7227000000da046c6973742908727c0000007209000000da12736f727465645f72616e6b5f76616c756573da0a706c617965725f736574da0472616e6bda11706c61796572735f776974685f72616e6b7280000000da0777696e6e657273720b000000720b000000720c000000da0e5f5f66696e645f77696e6e657273c800000073120000000001100108010a0108010e010c010801060172870000002905720900000072200000007226000000da0e63757272656e745f6265747465727208000000630400000000000000060000000400000003000000736e00000074008801830174007c008301640118006b0572186400530074007c0083017400880083016b02722c640053008700870166026402640384087c00440083017d0474007c04830164016b027250640053007c046a017c0383017d057c047c056401170074007c04830116001900530029044e7202000000630100000000000000020000000400000013000000732000000067007c005d187d017c0188016b0772047c0188006b0772047c01910271045300720b000000720b0000002902da022e30da0170290272260000007220000000720b000000720c000000fa0a3c6c697374636f6d703eda000000730400000006000c017a255f5f6765745f6e6578745f6265747465722e3c6c6f63616c733e2e3c6c697374636f6d703e29027227000000720e00000029067209000000722000000072260000007288000000da126e6f6e5f666f6c6465645f706c6179657273da0d63757272656e745f696e646578720b000000290272260000007220000000720c0000007262000000d400000073120000000002140104011001040114020c0104010a01726200000029097228000000722b0000007250000000722300000072200000007226000000721b000000721c00000072080000006308000000000000000c000000050000004300000073c00000007c0174006b0273107c0174016b0272b07c077c00640166021900701e64027d087c08640337007d087c087c077c00640166023c007c0864046b02724a64057c077c00640666023c0071bc7c036a027c0683017d097846740374047c03830164031800830144005d327d0a7c037c097c0a17006403170074047c038301160019007d0b7c0b7c046b0772667c0b7c056b0772667c0b7d0250007166570064057c077c0064077c089b009d0266023c006e0c64057c077c00640666023c007c02530029084eda05726f756e64720100000072020000007205000000547221000000da0c6e656564735f72657665616c290572340000007235000000720e00000072550000007227000000290c7228000000722b0000007250000000722300000072200000007226000000721b000000721c000000728e00000072790000007265000000720f000000720b000000720b000000720c000000da155f5f68616e646c655f646f6e655f62657474696e67e2000000732000000000031001100108010c0108010e020a0116010e010a0110010401060114020c0172900000002904720f0000007228000000721c000000720800000063030000000000000003000000040000004300000073360000007c027c017c0064016603190064006b096f347c027c017c0064026603190064006b096f347c027c017c0064036603190064006b09530029044e726c000000726d000000726e000000720b0000002903720f0000007228000000721c000000720b000000720b000000720c000000da145f5f61737365727452657665616c65644f747073f90000007306000000000116011a017291000000290572280000007230000000720f0000007207000000721c00000063050000000000000017000000090000004300000073620300007c047c007c0264016603190064006b09731a74006402830182017c047c006403660219000c00733074006404830182017c047c006405660219007c026b02734874006406830182017c047c006407660219007d057c047c006408660219007d067c047c006409660219007d077c047c00640a66021900707a640b7d087c047c007c02640c66031900708c640b7d097c047c00640d660219007d0a74017c057c067c077c0283047d0b7c0b64006b0872c0640e7c047c00640366023c0090026e927c056a027c0b83017d0c7c056a027c0283017d0d7c0c7c0d6b007d0e7c047c00640f660219007d0f7c037c0f6410660219007d107c1074036b02900173087c1074046b029001724c7c047c006411660219007d117c1164006b099001724c7c1174057406740766036b069001724c7c047c0064127c119b009d02660219000c009001734c74006413830182017c047c007c0b640c660319007d127c01640b6b00900172ee7c1074036b02900173787c1074046b029001728e74087c027c007c0483039001738e74006414830182017c066a097c02830101007c067c047c00640866023c007c027c076b06900172c47c076a0a7c02830101007c077c047c00640966023c00740b7c068301740b7c058301641518006b02900172e6640e7c047c00640366023c007c087d1390016e347c01640b6b02900272367c047c007c026416660319007d147c147c096b02900272307c027c076b07900272307c076a097c02830101007c077c047c00640966023c007c097d136ed07c037c0f7c02660219007c016b059002735074006417830182017c037c0f6418660219007d157c15740c6b02900272847c047c006419660219007d167c017c166b01900273847400641a830182017c097c0117007d137c047c007c026416660319007d147c147c136b02900272c47c027c076b07900272c47c076a097c02830101007c077c047c00640966023c007c137c047c007c02640c66033c007c137c047c00640a66023c007c047c0064196602050019007c01370003003c007c037c0f7c026602050019007c01380003003c007c147c136b02900373227c137c086b05900373227400641b830182017c0e900372527c1264006b09900372527c127c136b0290037252740d7c007c107c0b7c057c067c077c0a7c0483087d0b7c0b7c047c00640566023c0064005300291c4e724e0000007a1348616e6420646f6573206e6f7420657869737472210000007a20546869732068616e642068617320616c726561647920636f6d706c657465642e72500000007a1b4974206973206e6f7420796f7572207475726e20746f206265742e722300000072200000007226000000722400000072010000007230000000721b000000547206000000722b000000728e000000728f0000007a30526571756972656420636f6d6d756e6974792063617264732068617665206e6f74206265656e2072657665616c65642e7a32506c656173652072657665616c20796f757220706f7274696f6e206f662074686520636f6d6d756e6974792063617264732e720200000072310000007a2d596f7520646f206e6f74206861766520656e6f75676820636869707320746f206d616b65207468697320626574da086265745f7479706572250000007a2943616e6e6f74206f7665726265742074686520706f7420696e20706f742d6c696d6974206d6f64652e7a3843757272656e74206265742069732061626f766520796f75722062657420616e6420796f7520646964206e6f7420676f20616c6c20696e2e290e720a0000007262000000720e00000072350000007234000000da045455524eda04464c4f50da05524956455272910000007236000000da0672656d6f76657227000000da09504f545f4c494d49547290000000291772280000007230000000720f0000007207000000721c000000722300000072200000007226000000da0863616c6c5f626574da13706c617965725f70726576696f75735f626574721b0000007250000000da0a6e6578745f696e646578728d000000da12706f737369626c655f726f756e645f656e647206000000722b000000728e000000da106e6578745f706c61796572735f6265747224000000723100000072920000007225000000720b000000720b000000720c000000da116265745f636865636b5f6f725f666f6c64ff000000738000000000030c010e0116010a010e010c010c010c01100112010c010e01080110020a010a0108010c010c0114010c011a01180106010e010a011401100106010a010c010a010a010c0116010c0108020a010e0114010a010c0106020a0110010c010a010c01120108010e0114010a010c010e010c01140114011c0110010a0106011001729d00000029067228000000da03706164726b000000720e000000720f000000721c00000063060000000000000008000000060000004300000073940000007c0374007401740266036b06731674036401830182017c057c006402660219007d067c0664006b09733274036403830182017c066a047c0483017d077c0764046b05734c740364058301820174056a067c019b0064067c029b009d0383017c057c007c0464077c039b009d02660319006b02737c74036408830182017c017c057c007c0464097c039b009d0266033c0064005300290a4e7a0e496e76616c696420696e6465782e72230000007a19546869732068616e6420646f6573206e6f742065786973742e72010000007a19596f7520617265206e6f7420696e20746869732068616e642e7213000000da13686f7573655f656e637279707465645f7061647a14496e76616c6964206b6579206f722073616c742e729e0000002907729400000072930000007295000000720a000000720e0000007214000000721500000029087228000000729e000000726b000000720e000000720f000000721c0000007223000000da0c706c617965725f696e646578720b000000720b000000720c000000da0a72657665616c5f6f7470470100007310000000000316010c0110010a0110011801180172a100000029047228000000720e000000721c00000072080000006303000000000000000a000000060000004300000073f80000007c0174007401740266036b06731674036401830182017c027c006402660219007d037c027c006403660219007d047c027c006404660219007c016405180019007d0574047c0383017d06787e74057c06830144005d727d077c03640c7c07180019007d087c027c007c0864067c019b009d02660319007d097c0964006b097390740364077c089b0064089d03830182017c077c06640518006b0372b274066a077c0574087c0983016409640a8d037d05715474066a097c0574087c0983016409640a8d037d05715457007c057c047c01640518003c007c047c027c00640366023c0064097c027c00640b7c019b009d0266023c007c055300290d4e7a0e496e76616c696420696e6465782e7223000000725200000072510000007202000000729e0000007a07506c61796572207a1c20686173206e6f742072657665616c6564207468656972207061642e462903da0d656e637279707465645f737472725c0000007243000000728f000000e9ffffffff290a729400000072930000007295000000720a00000072270000007255000000725c000000da0b646563727970745f6865787261000000da0764656372797074290a7228000000720e000000721c00000072230000007252000000da03656e63da096e5f706c61796572737265000000720f000000729e000000720b000000720b000000720c000000da0672657665616c540100007320000000000216010c010c01140108010e010c01140118010c01160218010c010c01120172a8000000290672280000007269000000720f0000007207000000721c000000720800000063050000000000000014000000060000004300000073500200007c047c00640166021900731474006402830182017c047c006403660219007d057c027c056b07733074006404830182017c047c006405660219007d067c027c066b06734c74006406830182017c047c006407660219007d077c0764006b09736874006408830182017c047c007c026409660319007d087c0864006b0973867400640a830182017c077c086b0273a67c027c047c00640b660219006b0673a67400640c8301820174016a027c0183017d097c047c007c02640d660319007d0a7c0a64006b096fcc7c0a7c096b027d0b7c0b73ec7c056a037c02830101007c057c047c00640366023c00640e53007c016a04640f8301641019006a04641183017d0c7c047c006412660219007d0d7c037c0d6413660219007d0e7c0e74056b029001729864107d0f786e7c0644005d667d107c107c026b039001722c7c107c056b07900172887c0c7c0f19007d1174066a077c11670183017d127c047c007c1064146603190064006b08900172887c127c047c007c10641466033c007c117c047c007c10641566033c007c0f641637007d0f9001712c57006eb07c0e74086b02900173ac7c0e74096b02900272227c047c006417660219007d137c1364006b09900173ca74006418830182017c136410190064006b09900172f47c136416190064006b09900172f47c136419190064006b09900173fc7400641a830182017c0c6a0a7c13641019006a0464118301830101007c0c6a0a7c1364166400850219008301010074066a077c0c83017d127c127c047c007c02641466033c007c0c7c047c007c02641566033c00641b530064005300291c4e72210000007a20546869732068616e6420686173206e6f7420636f6d706c65746564207965742e72200000007a2f4e6f206e65656420746f2076657269667920796f75722068616e64206265636175736520796f7520666f6c6465642e72230000007a2a596f7520617265206e6f7420616e2061637469766520706c6179657220696e20746869732068616e642e72240000007a185468657265206973206e6f2063757272656e74206265742e72300000007a15596f752068617665206e6f7420626574207965742e72260000007a19426574732068617665206e6f742073746162696c697a65642e724f0000007a32566572696669636174696f6e206661696c65642e20596f75722068616e6420686173206265656e20666f726665697465642e72130000007201000000723d0000007206000000722b0000007284000000da0468616e64720200000072520000007a28506c656173652072657665616c2074686520636f6d6d756e6974792063617264732066697273742e72030000007a22506c656173652072657665616c20616c6c20636f6d6d756e6974792063617264732e7a17566572696669636174696f6e207375636365656465642e290b720a000000721400000072150000007236000000725600000072580000007253000000da086576616c7561746572340000007235000000da06657874656e64291472280000007269000000720f0000007207000000721c00000072200000007223000000da106265745f73686f756c645f657175616cda0a706c617965725f626574724f000000da1d70726576696f75735f686f7573655f656e637279707465645f68616e64da08766572696669656472630000007206000000722b000000da016a728a000000da046361726472840000007252000000720b000000720b000000720c000000da0b7665726966795f68616e6469010000735c000000000314010c0110010c0110010c0110010e0110011a0106010a01060108010801080104010a010c01040214010c010c010a0104010a010a010a0108010c0114010e010e01100214010c01120114010e011001140112010a010e010e0172b2000000290472280000007209000000721c0000007208000000630300000000000000060000000500000043000000735a00000069007d0378507c0144005d487d047c027c007c046401660319007d057c0564006b097334740064027c049b0064039d03830182017c057c036b07724467007c037c053c007c037c0519006a017c0483010100710a57007c03530029044e72840000007a07506c61796572207a2120686173206e6f742076657269666965642074686569722068616e64207965742e2902720a0000007236000000290672280000007209000000721c000000727c000000728a0000007284000000720b000000720b000000720c000000da115f5f63616c63756c6174655f72616e6b739e0100007310000000000104010a010e01180108010801120172b3000000290372280000007207000000721c0000006303000000000000001a0000000600000003000000730e0300007c027c006401660219007d037c0364026b04731c74006403830182017c027c006404660219000c00733274006405830182017c027c0064066602190089007c027c006407660219007d047c027c006408660219007d05870066016409640a84087c05440083017d0674017c06830164026b04737c7400640b8301820169007d0774017c068301640c6b02729c7c037c077c06640219003c0090026e0a74027c007c067c0283037d0874017c04830164026b049002727869007d0978227c0444005d1a7d0a7c027c007c0a640d660319007d0b7c0b7c097c0a3c0071c0570074037c096a04830083017d0c67007d0d781e7c0c44005d167d0e7c0e7c0d6b0772f47c0d6a057c0e8301010071f4570064027d0f64027d1078ac7c0d44005da47d0e67007d1178307c0644005d287d0a7c0a7c096b07900173467c097c0a19007c0e6b059001722a7c116a057c0a830101009001712a570074067c087c1183027d127c0e74017c11830114007c1018007d137c0f7c1337007d0f7c1374017c1283011b007d1478307c1244005d287d157c157c076b07900172a064027c077c153c007c077c15050019007c14370003003c009001718a57007c107c1337007d109001711c57007c037c0f18007d1674077c0683016a0874077c04830183017d177c1664026b05900173f07400640e830182017c1664026b029002731074017c17830164026b04900273107400640f830182017c1664026b04900272a674017c178301640c6b029002722e7c177d186e0a74067c087c1783027d187c1674017c1883011b007d1478607c1844005d287d157c157c076b079002726064027c077c153c007c077c15050019007c14370003003c009002714a57006e2e74067c087c0683027d187c0374017c1883011b007d1478167c1844005d0e7d157c147c077c153c009002719457007c027c006410660219007d19782a7c076a09830044005d1e5c027d0a7d147c017c197c0a6602050019007c14370003003c00900271bc5700740a7c076a0b830083017c027c00641166023c007c077c027c00641266023c0064137c027c00640466023c006400530029144e722500000072010000007a195468657265206973206e6f20706f7420746f20636c61696d21721e0000007a25546869732068616e642068617320616c7265616479206265656e207061796564206f75742e722000000072260000007223000000630100000000000000020000000400000013000000731800000067007c005d107d017c0188006b0772047c01910271045300720b000000720b00000029027289000000728a00000029017220000000720b000000720c000000728b000000b2010000730200000006007a1f7061796f75745f68616e642e3c6c6f63616c733e2e3c6c697374636f6d703e7a1f546865726520617265206e6f2072656d61696e696e6720706c61796572732e720200000072310000007a1c496e76616c69642072656d61696e696e6720746f207061796f75742e7a29496e76616c6964207374617465207768656e2063616c63756c6174696e67207369646520706f74732e72060000007286000000da077061796f75747354290c720a000000722700000072b3000000727e000000da0676616c75657372360000007287000000727f000000da0a646966666572656e6365da056974656d7372810000007267000000291a72280000007207000000721c000000722500000072260000007223000000da0972656d61696e696e6772b4000000727c000000da0a616c6c5f696e5f6d6170720f000000da06616d6f756e74da08616c6c5f706f7473da0b756e697175655f706f74737230000000da0f746f74616c5f70617965645f6f7574da1370726576696f75735f706f745f7061796f7574da0e706c61796572735f696e5f706f74da0b706f745f77696e6e657273da0a706f745f7061796f7574da067061796f7574da0677696e6e6572da1372656d61696e696e675f746f5f7061796f7574da0a6e6f745f616c6c5f696e72860000007206000000720b00000029017220000000720c000000da0b7061796f75745f68616e64a9010000737e00000000020c011001100106010c010c010c011201140104010c0110020c010e0104010a010e010c010c0104010a0108010e01040104010a0104010a01180110010a01100108010c010a010a01080116010e01080112011201100110010a010e0106020a010c010a010a01080118020a010c010a010e010c0112011a0114010c0172c6000000290672060000007228000000720f000000da05666f726365721c00000072070000006306000000000000000d000000050000004300000073100100007c047c01640166021900700e67007d067c027c066b069001720c7c03733a7c047c016402660219007d077c027c076b03733a74006403830182017c047c016404660219007d087c047c016405660219007d097c047c016406660219007d0a7c057c006407660219007d0b7c0b74016b02737a7c0b74026b0272ac74037c027c017c0483037d0c7c0372a07c0c0c0072a074047c007c017c047c05830401006e0c7c0c73ac74006408830182017c0a7c026b0272ce74057c067c087c097c0283047d0a7c0a7c047c01640666023c007c027c086b0772ec7c086a067c02830101007c087c047c01640466023c007c027c096b069001720c7c096a077c02830101007c097c047c01640566023c006400530029094e7223000000721b0000007a194465616c65722063616e6e6f74206c656176652068616e642e722000000072260000007250000000722b0000007a32506c656173652072657665616c20796f757220706f7274696f6e206f662074686520636f6d6d756e6974792063617264732e2908720a000000723500000072340000007291000000da115f5f666f7263655f756e646f5f68616e64726200000072360000007296000000290d72060000007228000000720f00000072c7000000721c00000072070000007223000000721b000000722000000072260000007250000000722b000000da0c6861735f72657665616c6564720b000000720b000000720c000000da0a6c656176655f68616e64ef0100007330000000000310010a0104010c0110010c010c010c010c0110010c010a0110020c010801080106010c0108010a010c010a010a0172ca000000290472060000007228000000721c000000720700000063040000000000000007000000050000004300000073740000007c027c01640166021900700e67007d0464027c027c01640366023c0064027c027c01640466023c0064027c027c01640566023c00783a7c0444005d327d057c027c017c05640666031900704e64077d067c0664076b04723a7c037c007c056602050019007c06370003003c00713a57006400530029084e722300000054da0a666f7263655f756e646f7221000000721e00000072300000007201000000720b000000290772060000007228000000721c00000072070000007223000000720f0000007230000000720b000000720b000000720c00000072c80000000d0200007310000000000110010c010c010c010a011201080172c8000000292dda12636f6e5f7273615f656e6372797074696f6e7260000000da0a636f6e5f6f74705f7631725c000000da15636f6e5f68616e645f6576616c7561746f725f763172530000007259000000da047365656472570000007258000000723300000072340000007235000000725b000000da084e4f5f4c494d495472970000007294000000729300000072950000007217000000da03416e79da0464696374720d0000007281000000726100000072110000007219000000da085f5f6578706f72747229000000723a000000727b000000728700000072620000007290000000da04626f6f6c7291000000da05666c6f6174729d00000072a100000072a800000072b200000072b300000072c600000072ca00000072c8000000720b000000720b000000720b000000720c000000da083c6d6f64756c653e0100000073620000000801080108010801040104010401040104010401040104010401040104031206100710040601181806011623060108011066120c0601100d06010a010e15140606010801104606010a01100b06011614060108011233140b0601144506010801121c