|
@@ -1,7 +1,10 @@
|
|
|
-from random import randint, gauss
|
|
|
+from random import randint, gauss, shuffle
|
|
|
from datetime import datetime, timedelta
|
|
|
+import pickle
|
|
|
|
|
|
-from rollbot import as_plugin, with_help, with_startup, as_sender_singleton, RollbotFailure
|
|
|
+from sudoku_py import SudokuGenerator, Sudoku
|
|
|
+
|
|
|
+from rollbot import as_plugin, with_help, with_startup, as_sender_singleton, as_group_singleton, RollbotFailure
|
|
|
|
|
|
|
|
|
@as_sender_singleton
|
|
@@ -14,6 +17,22 @@ class RollcoinBegCooldown:
|
|
|
cooldown: datetime = datetime(2000, 1, 1)
|
|
|
|
|
|
|
|
|
+@as_group_singleton
|
|
|
+class RollcoinBlockchain:
|
|
|
+ puzzle: "binary"
|
|
|
+
|
|
|
+ def get_puzzle(self):
|
|
|
+ if self.puzzle is None:
|
|
|
+ return None
|
|
|
+ return pickle.loads(self.puzzle)
|
|
|
+
|
|
|
+ def set_puzzle(self, new_puzzle):
|
|
|
+ self.puzzle = pickle.dumps(new_puzzle)
|
|
|
+
|
|
|
+ def clear_puzzle(self):
|
|
|
+ self.puzzle = None
|
|
|
+
|
|
|
+
|
|
|
def setup_initial_balances(plugin, db):
|
|
|
bot = plugin.bot
|
|
|
bot.logger.info("Setting up rollcoin wallets")
|
|
@@ -73,8 +92,58 @@ def tip(msg, db, sender_wallet_data: RollcoinWallet, wallet_cfg: "rollcoin.walle
|
|
|
|
|
|
@with_help("Receive a mining question you can answer to receive Rollcoins")
|
|
|
@as_plugin
|
|
|
-def mine():
|
|
|
- return "Mining is still being worked on! Have you tried to !beg?"
|
|
|
+def mine(msg, blockchain_data: RollcoinBlockchain, sender_data: RollcoinWallet):
|
|
|
+ puzzle = blockchain_data.get_puzzle()
|
|
|
+ if puzzle is None:
|
|
|
+ exchange = list(zip("abcdefghi", range(10)))
|
|
|
+ shuffle(exchange)
|
|
|
+ gen = SudokuGenerator(9)
|
|
|
+ gen.generate(0)
|
|
|
+ gen.board_exchange_values({k: v + 1 for k, v in exchange})
|
|
|
+ gen.generate(randint(10, 70))
|
|
|
+ puzzle = gen.board
|
|
|
+ blockchain_data.set_puzzle(puzzle)
|
|
|
+
|
|
|
+ if msg.raw_args is None:
|
|
|
+ return "The current mining challenge is\n" + str(Sudoku(board=puzzle))
|
|
|
+
|
|
|
+ parsed = []
|
|
|
+ row = []
|
|
|
+ for c in msg.raw_args:
|
|
|
+ if not c.isdigit():
|
|
|
+ continue
|
|
|
+ row.append(int(c))
|
|
|
+ if len(row) == 9:
|
|
|
+ parsed.append(row)
|
|
|
+ row = []
|
|
|
+
|
|
|
+ try:
|
|
|
+ guess = Sudoku(board=parsed, block_width=3, block_height=3)
|
|
|
+ except:
|
|
|
+ return "Sorry, I could not parse that solution!"
|
|
|
+
|
|
|
+ for i, row in enumerate(puzzle):
|
|
|
+ for j, cell in enumerate(row):
|
|
|
+ if cell not in (0, parsed[i][j]):
|
|
|
+ return "Sorry, that solution doesn't match the puzzle! The current mining challenge is\n" + str(Sudoku(board=puzzle))
|
|
|
+
|
|
|
+ for row in parsed:
|
|
|
+ if set(row) != set(range(1, 10)):
|
|
|
+ return "Sorry, that solution isn't valid!"
|
|
|
+
|
|
|
+ for i in range(9):
|
|
|
+ if set(r[i] for r in parsed) != set(range(1, 10)):
|
|
|
+ return "Sorry, that solution isn't valid!"
|
|
|
+
|
|
|
+ for i in range(0, 9, 3):
|
|
|
+ for j in range(0, 9, 3):
|
|
|
+ if set(x for r in parsed[i:i+3] for x in r[j:j+3]) != set(range(1, 10)):
|
|
|
+ return "Sorry, that solution isn't valid!"
|
|
|
+
|
|
|
+ market_rate = round(abs(gauss(10, 1)), 2)
|
|
|
+ sender_data.balance = sender_data.balance + market_rate
|
|
|
+ blockchain_data.clear_puzzle()
|
|
|
+ return f"Looks right to me! The current market rate is {market_rate} Rollcoins per Sudoku, so that brings your balance to {sender_data.balance}"
|
|
|
|
|
|
|
|
|
@with_help("Beg for some Rollcoins")
|