Explorar el Código

Implement ability to trade sudokus for rollcoins

Kirk Trombley hace 4 años
padre
commit
c0f97ae0f5
Se han modificado 2 ficheros con 74 adiciones y 4 borrados
  1. 1 0
      requirements.txt
  2. 73 4
      src/plugins/rollcoin.py

+ 1 - 0
requirements.txt

@@ -7,3 +7,4 @@ dice
 requests_html
 pillow
 gTTS
+sudoku-py

+ 73 - 4
src/plugins/rollcoin.py

@@ -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")