pokerbots-dev 0.1.1__tar.gz → 0.1.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. {pokerbots_dev-0.1.1 → pokerbots_dev-0.1.3}/PKG-INFO +1 -1
  2. {pokerbots_dev-0.1.1 → pokerbots_dev-0.1.3}/pyproject.toml +1 -1
  3. {pokerbots_dev-0.1.1 → pokerbots_dev-0.1.3}/src/pokerbots_cli/commands/account.py +33 -7
  4. {pokerbots_dev-0.1.1 → pokerbots_dev-0.1.3}/src/pokerbots_cli/docs.md +1 -0
  5. pokerbots_dev-0.1.3/src/pokerbots_cli/fmt.py +55 -0
  6. pokerbots_dev-0.1.1/src/pokerbots_cli/fmt.py +0 -23
  7. {pokerbots_dev-0.1.1 → pokerbots_dev-0.1.3}/.gitignore +0 -0
  8. {pokerbots_dev-0.1.1 → pokerbots_dev-0.1.3}/README.md +0 -0
  9. {pokerbots_dev-0.1.1 → pokerbots_dev-0.1.3}/src/pokerbots_cli/__init__.py +0 -0
  10. {pokerbots_dev-0.1.1 → pokerbots_dev-0.1.3}/src/pokerbots_cli/agent.py +0 -0
  11. {pokerbots_dev-0.1.1 → pokerbots_dev-0.1.3}/src/pokerbots_cli/api.py +0 -0
  12. {pokerbots_dev-0.1.1 → pokerbots_dev-0.1.3}/src/pokerbots_cli/auth.py +0 -0
  13. {pokerbots_dev-0.1.1 → pokerbots_dev-0.1.3}/src/pokerbots_cli/cards.py +0 -0
  14. {pokerbots_dev-0.1.1 → pokerbots_dev-0.1.3}/src/pokerbots_cli/commands/__init__.py +0 -0
  15. {pokerbots_dev-0.1.1 → pokerbots_dev-0.1.3}/src/pokerbots_cli/commands/admin.py +0 -0
  16. {pokerbots_dev-0.1.1 → pokerbots_dev-0.1.3}/src/pokerbots_cli/commands/local.py +0 -0
  17. {pokerbots_dev-0.1.1 → pokerbots_dev-0.1.3}/src/pokerbots_cli/commands/money.py +0 -0
  18. {pokerbots_dev-0.1.1 → pokerbots_dev-0.1.3}/src/pokerbots_cli/engine.py +0 -0
  19. {pokerbots_dev-0.1.1 → pokerbots_dev-0.1.3}/src/pokerbots_cli/house.py +0 -0
  20. {pokerbots_dev-0.1.1 → pokerbots_dev-0.1.3}/src/pokerbots_cli/main.py +0 -0
  21. {pokerbots_dev-0.1.1 → pokerbots_dev-0.1.3}/src/pokerbots_cli/template/bot.py +0 -0
  22. {pokerbots_dev-0.1.1 → pokerbots_dev-0.1.3}/src/pokerbots_cli/wallet.py +0 -0
  23. {pokerbots_dev-0.1.1 → pokerbots_dev-0.1.3}/tests/test_agent.py +0 -0
  24. {pokerbots_dev-0.1.1 → pokerbots_dev-0.1.3}/tests/test_cards.py +0 -0
  25. {pokerbots_dev-0.1.1 → pokerbots_dev-0.1.3}/tests/test_cli.py +0 -0
  26. {pokerbots_dev-0.1.1 → pokerbots_dev-0.1.3}/tests/test_engine.py +0 -0
  27. {pokerbots_dev-0.1.1 → pokerbots_dev-0.1.3}/tests/test_wallet.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: pokerbots-dev
3
- Version: 0.1.1
3
+ Version: 0.1.3
4
4
  Summary: pb: command-line client for pokerbots.dev
5
5
  Project-URL: Homepage, https://pokerbots.dev
6
6
  Project-URL: Source, https://github.com/pokerbots-dev/pokerbots
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "pokerbots-dev"
7
- version = "0.1.1"
7
+ version = "0.1.3"
8
8
  description = "pb: command-line client for pokerbots.dev"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -1,13 +1,15 @@
1
1
  import io
2
2
  import sys
3
+ import time
3
4
  import zipfile
4
5
  from pathlib import Path
5
6
 
6
7
  from .. import auth
7
8
  from ..api import call
8
- from ..fmt import money, place, table
9
+ from ..fmt import INK, PAPER, colored, money, place, signed, table, when
9
10
 
10
11
  MAX_UPLOAD = 1 << 20
12
+ WATCH_SECONDS = 5
11
13
  ATTEST = "I am 18 or older, and paid skill competitions are allowed where I am. [y/N] "
12
14
 
13
15
 
@@ -54,20 +56,43 @@ def stop(args):
54
56
  print(f"stopped {mode}")
55
57
 
56
58
 
57
- def status(args):
59
+ def report():
58
60
  me = call("GET", "/me")
59
61
  rows = [["user", me["login"]], ["versions", " ".join(f"v{v}" for v in me["versions"]) or "-"]]
60
62
  for mode in ("paper", "live"):
61
63
  d = me["deployments"].get(mode)
62
64
  rows.append([mode, f"v{d['version']} rating {d['rating']:.0f} games {d['games']} today {d['today']}" if d else "-"])
63
65
  rows += [["balance", money(me["balance"])], ["wallet", me["wallet"] or "-"]]
64
- print(table(rows))
66
+ text = table(rows, labels=True)
65
67
  games = call("GET", "/games")
66
68
  if games:
67
- print()
68
- print(table([["game", "mode", "place", "hands"]] + [
69
- [g["created_at"], g["mode"], place(g["place"]), g["hands"] or "-"] for g in games
70
- ]))
69
+ live = any(g["mode"] == "live" for g in games)
70
+ head = ["game", "mode", "place", "hands", "rating"] + (["won"] if live else [])
71
+ text += "\n\n" + table([head] + [
72
+ [when(g["created_at"]), g["mode"], place(g["place"]), g["hands"] or "-", signed(g.get("rating_delta"))]
73
+ + ([signed(g.get("net"), "money")] if live else [])
74
+ for g in games
75
+ ], header=True)
76
+ return text
77
+
78
+
79
+ def status(args):
80
+ print(report())
81
+
82
+
83
+ def watch(args):
84
+ paint = f"\x1b[48;2;{INK}m\x1b[38;2;{PAPER}m" if colored() else ""
85
+ sys.stdout.write("\x1b[?1049h\x1b[?25l" + paint + "\x1b[2J")
86
+ try:
87
+ while True:
88
+ lines = ["", *(" " + line for line in report().split("\n")), "", " " + "ctrl-c to quit"]
89
+ sys.stdout.write("\x1b[H" + "".join(line + "\x1b[K\n" for line in lines) + "\x1b[J")
90
+ sys.stdout.flush()
91
+ time.sleep(WATCH_SECONDS)
92
+ except KeyboardInterrupt:
93
+ pass
94
+ finally:
95
+ sys.stdout.write("\x1b[0m\x1b[?25h\x1b[?1049l")
71
96
 
72
97
 
73
98
  def register(sub):
@@ -87,3 +112,4 @@ def register(sub):
87
112
  p.set_defaults(run=run)
88
113
 
89
114
  sub.add_parser("status", help="your bot, rating, balance and recent games").set_defaults(run=status)
115
+ sub.add_parser("watch", help="status, live").set_defaults(run=watch)
@@ -9,6 +9,7 @@ start
9
9
  pb deploy v1 --live play for money with v1
10
10
  pb stop --paper|--live stop playing
11
11
  pb status versions, rating, balance, recent games
12
+ pb watch the same, refreshed every 5 seconds
12
13
  pb docs [--plain] show this
13
14
 
14
15
  money
@@ -0,0 +1,55 @@
1
+ import os
2
+ import sys
3
+ from datetime import datetime, timezone
4
+
5
+ MICRO = 1_000_000
6
+ INK, PAPER = "17;17;17", "244;243;239"
7
+
8
+
9
+ def colored():
10
+ return sys.stdout.isatty() and not os.environ.get("NO_COLOR")
11
+
12
+
13
+ def bold(text):
14
+ return f"\x1b[1m{text}\x1b[22m" if colored() else text
15
+
16
+
17
+ def table(rows, labels=False, header=False):
18
+ """Aligned columns; bold the first column (labels) or first row (header)."""
19
+ rows = [[str(c) for c in row] for row in rows]
20
+ widths = [max(len(r[i]) for r in rows if i < len(r)) for i in range(max(map(len, rows)))]
21
+ lines = []
22
+ for n, r in enumerate(rows):
23
+ cells = [c.ljust(w) for c, w in zip(r, widths)]
24
+ if header and n == 0:
25
+ cells = [bold(c) for c in cells]
26
+ elif labels:
27
+ cells[0] = bold(cells[0])
28
+ lines.append(" ".join(cells).rstrip())
29
+ return "\n".join(lines)
30
+
31
+
32
+ def money(micro):
33
+ cents = round(micro / 10_000)
34
+ return f"{cents}¢" if abs(cents) < 100 else f"${cents / 100:,.2f}"
35
+
36
+
37
+ def signed(value, unit=""):
38
+ if value is None:
39
+ return "-"
40
+ return ("+" if value > 0 else "") + (money(value) if unit == "money" else f"{value:.0f}")
41
+
42
+
43
+ def when(utc):
44
+ return datetime.fromisoformat(utc).replace(tzinfo=timezone.utc).astimezone().strftime("%m-%d %H:%M")
45
+
46
+
47
+ def parse_money(text):
48
+ value = round(float(text.lstrip("$")) * MICRO)
49
+ if value <= 0:
50
+ raise ValueError("amount must be positive")
51
+ return value
52
+
53
+
54
+ def place(n):
55
+ return {1: "1st", 2: "2nd", 3: "3rd"}.get(n, f"{n}th") if n else "-"
@@ -1,23 +0,0 @@
1
- MICRO = 1_000_000
2
-
3
-
4
- def table(rows):
5
- rows = [[str(c) for c in row] for row in rows]
6
- widths = [max(len(r[i]) for r in rows if i < len(r)) for i in range(max(map(len, rows)))]
7
- return "\n".join(" ".join(c.ljust(w) for c, w in zip(r, widths)).rstrip() for r in rows)
8
-
9
-
10
- def money(micro):
11
- cents = round(micro / 10_000)
12
- return f"{cents}¢" if abs(cents) < 100 else f"${cents / 100:,.2f}"
13
-
14
-
15
- def parse_money(text):
16
- value = round(float(text.lstrip("$")) * MICRO)
17
- if value <= 0:
18
- raise ValueError("amount must be positive")
19
- return value
20
-
21
-
22
- def place(n):
23
- return {1: "1st", 2: "2nd", 3: "3rd"}.get(n, f"{n}th") if n else "-"
File without changes
File without changes