phihung commited on
Commit
76781ed
·
1 Parent(s): d99ea12

Store game in session instead of cookie

Browse files
Files changed (7) hide show
  1. .gitignore +3 -1
  2. Dockerfile +2 -2
  3. pyproject.toml +1 -1
  4. src/wordle/game.py +1 -1
  5. src/wordle/tw.py +9 -2
  6. src/wordle/ui.py +31 -19
  7. uv.lock +1 -1
.gitignore CHANGED
@@ -1,4 +1,6 @@
1
  .venv
2
  app.css
3
  .sesskey
4
- __pycache__
 
 
 
1
  .venv
2
  app.css
3
  .sesskey
4
+ __pycache__
5
+ .vscode/
6
+ tailwind.config.js
Dockerfile CHANGED
@@ -15,6 +15,6 @@ COPY --chown=user src ./src
15
  RUN touch README.md
16
 
17
  RUN uv sync --frozen
18
- RUN . .venv/bin/activate
19
 
20
- CMD ["uv", "run", "python", "src/wordle/ui.py"]
 
 
15
  RUN touch README.md
16
 
17
  RUN uv sync --frozen
 
18
 
19
+ # CMD ["uv", "run", "python", "src/wordle/ui.py"]
20
+ CMD ["uv", "run", "uvicorn", "--port", "5001", "--host", "0.0.0.0", "wordle.ui:app"]
pyproject.toml CHANGED
@@ -5,7 +5,7 @@ description = "A simple wordle clone with fasthtml"
5
  readme = "README.md"
6
  requires-python = ">=3.10"
7
  dependencies = [
8
- "python-fasthtml>=0.4.5",
9
  ]
10
 
11
  # [tool.uv.sources]
 
5
  readme = "README.md"
6
  requires-python = ">=3.10"
7
  dependencies = [
8
+ "python-fasthtml>=0.4.6",
9
  ]
10
 
11
  # [tool.uv.sources]
src/wordle/game.py CHANGED
@@ -68,7 +68,7 @@ class Game:
68
  # Return updated squares and keys
69
  def keypress(self, key: str):
70
  keys = []
71
- if key == "ENTER":
72
  word = self.current
73
  squares = self._enter()
74
  keys = word if squares else []
 
68
  # Return updated squares and keys
69
  def keypress(self, key: str):
70
  keys = []
71
+ if key == "GO":
72
  word = self.current
73
  squares = self._enter()
74
  keys = word if squares else []
src/wordle/tw.py CHANGED
@@ -11,6 +11,7 @@ app, rt = fast_app(hdrs=[
11
  )
12
 
13
  # Add public/app.css to your .gitignore
 
14
  ```
15
 
16
  Acknowledgement: This code is heavily inspired by the [pytailwindcss](https://github.com/timonweb/pytailwindcss) project.
@@ -54,7 +55,13 @@ class Tailwind:
54
  `public/app.css` should be in .gitignore
55
  """
56
 
57
- def __init__(self, static_path = None, filename="app.css", cfg: str = DEFAULT_CONFIG, css: str = DEFAULT_SOURCE_CSS):
 
 
 
 
 
 
58
  self.dir = tempfile.TemporaryDirectory()
59
  path = Path(self.dir.name)
60
  if static_path is None:
@@ -81,7 +88,7 @@ class Tailwind:
81
  )
82
  subprocess.run([str(cli)] + args, **kwargs)
83
  return self
84
-
85
  def get_link_tag(self):
86
  from fasthtml.common import Link
87
 
 
11
  )
12
 
13
  # Add public/app.css to your .gitignore
14
+ # serve(reload_excludes=["public/app.css"])
15
  ```
16
 
17
  Acknowledgement: This code is heavily inspired by the [pytailwindcss](https://github.com/timonweb/pytailwindcss) project.
 
55
  `public/app.css` should be in .gitignore
56
  """
57
 
58
+ def __init__(
59
+ self,
60
+ static_path=None,
61
+ filename="app.css",
62
+ cfg: str = DEFAULT_CONFIG,
63
+ css: str = DEFAULT_SOURCE_CSS,
64
+ ):
65
  self.dir = tempfile.TemporaryDirectory()
66
  path = Path(self.dir.name)
67
  if static_path is None:
 
88
  )
89
  subprocess.run([str(cli)] + args, **kwargs)
90
  return self
91
+
92
  def get_link_tag(self):
93
  from fasthtml.common import Link
94
 
src/wordle/ui.py CHANGED
@@ -1,4 +1,4 @@
1
- from fasthtml.common import fast_app, Div, serve, Button, cookie, H1
2
  from wordle.tw import Tailwind
3
  from wordle.game import Eval, Game, State
4
 
@@ -6,18 +6,22 @@ from wordle.game import Eval, Game, State
6
  app, rt = fast_app(hdrs=[Tailwind("./").run().get_link_tag()], pico=False, static_path="./")
7
 
8
 
9
- @rt("/")
10
- def get(data: str = None):
11
- return make_app(Game.from_str(data))
 
 
12
 
13
 
14
- @rt("/new")
15
- def post():
16
- return make_app(Game.from_str(None))
 
 
17
 
18
 
19
- def make_app(g: "Game"):
20
- return cookie("data", g.to_str()), Div(
21
  Div(
22
  H1(Button("WORDLE", hx_post="/new"), cls="text-3xl font-bold"),
23
  cls="w-full flex flex-row place-content-center text-black",
@@ -41,18 +45,25 @@ def make_app(g: "Game"):
41
 
42
 
43
  @rt("/keypress")
44
- def put(key: str, data: str = None):
45
- g = Game.from_str(data)
 
 
 
 
 
 
 
46
  squares, keys = g.keypress(key)
 
47
  return (
48
- cookie("data", g.to_str()),
49
  *[make_square(g, i) for i in squares],
50
  *[make_key(g, k) for k in keys],
51
  make_status(g),
52
  )
53
 
54
 
55
- def make_status(g: "Game"):
56
  msgs = {State.WIN: "You win", State.LOSE: "You lose"}
57
  return Div(
58
  msgs.get(g.state),
@@ -62,7 +73,7 @@ def make_status(g: "Game"):
62
  )
63
 
64
 
65
- def make_square(g: "Game", i):
66
  cls = "grid h-12 w-12 sm:h-14 sm:w-14 place-items-center rounded-sm text-2xl font-bold"
67
  c, state = g.get_square_state(i)
68
  styles = {
@@ -75,10 +86,10 @@ def make_square(g: "Game", i):
75
  return Div(c, cls=cls + " " + styles[state], id=f"sq{i}", hx_swap_oob="true")
76
 
77
 
78
- def make_key(g: "Game", key: str):
79
  state = g.get_keyboard_state(key)
80
- cls = "grid h-14 cursor-pointer items-center rounded font-semibold"
81
- size = " p-2 sm:p-4 " if key == "ENTER" else " w-7 sm:w-10 "
82
  styles = {
83
  Eval.CORRECT: GREEN,
84
  Eval.EXIST: YELLOW,
@@ -93,6 +104,7 @@ def make_key(g: "Game", key: str):
93
 
94
 
95
  GREEN, YELLOW, GRAY = "bg-[#20AA57]", "bg-[#E5B22D]", "bg-[#989898]"
96
- KEYBOARD = [list("QWERTYUIOP"), list("ASDFGHJKL"), ["ENTER"] + list("ZXCVBNM") + ["DEL"]]
97
 
98
- serve(reload_excludes=["public/app.css"])
 
 
1
+ from fasthtml.common import fast_app, Div, serve, Button, H1
2
  from wordle.tw import Tailwind
3
  from wordle.game import Eval, Game, State
4
 
 
6
  app, rt = fast_app(hdrs=[Tailwind("./").run().get_link_tag()], pico=False, static_path="./")
7
 
8
 
9
+ @app.get("/")
10
+ def homepage(session):
11
+ if data := session.get("game"):
12
+ return make_app(Game.from_str(data))
13
+ return new_game.__wrapped__(session)
14
 
15
 
16
+ @app.post("/new")
17
+ def new_game(session):
18
+ g = Game.from_str(None)
19
+ session["game"] = g.to_str()
20
+ return make_app(g)
21
 
22
 
23
+ def make_app(g: Game):
24
+ return Div(
25
  Div(
26
  H1(Button("WORDLE", hx_post="/new"), cls="text-3xl font-bold"),
27
  cls="w-full flex flex-row place-content-center text-black",
 
45
 
46
 
47
  @rt("/keypress")
48
+ def put(session, key: str):
49
+ if "game" not in session:
50
+ return Div(
51
+ "The app does not work inside iframe. Try it here https://phihung-wordle.hf.space/",
52
+ cls="h-screen flex items-center justify-center text-xl",
53
+ hx_swap_oob="true",
54
+ id="app",
55
+ )
56
+ g = Game.from_str(session["game"])
57
  squares, keys = g.keypress(key)
58
+ session["game"] = g.to_str()
59
  return (
 
60
  *[make_square(g, i) for i in squares],
61
  *[make_key(g, k) for k in keys],
62
  make_status(g),
63
  )
64
 
65
 
66
+ def make_status(g: Game):
67
  msgs = {State.WIN: "You win", State.LOSE: "You lose"}
68
  return Div(
69
  msgs.get(g.state),
 
73
  )
74
 
75
 
76
+ def make_square(g: Game, i):
77
  cls = "grid h-12 w-12 sm:h-14 sm:w-14 place-items-center rounded-sm text-2xl font-bold"
78
  c, state = g.get_square_state(i)
79
  styles = {
 
86
  return Div(c, cls=cls + " " + styles[state], id=f"sq{i}", hx_swap_oob="true")
87
 
88
 
89
+ def make_key(g: Game, key: str):
90
  state = g.get_keyboard_state(key)
91
+ cls = "grid h-14 cursor-pointer items-center rounded font-semibold touch-manipulation"
92
+ size = " w-14 sm:w-16 " if len(key) > 1 else " w-9 sm:w-10 "
93
  styles = {
94
  Eval.CORRECT: GREEN,
95
  Eval.EXIST: YELLOW,
 
104
 
105
 
106
  GREEN, YELLOW, GRAY = "bg-[#20AA57]", "bg-[#E5B22D]", "bg-[#989898]"
107
+ KEYBOARD = [list("QWERTYUIOP"), list("ASDFGHJKL"), ["GO"] + list("ZXCVBNM") + ["DEL"]]
108
 
109
+ if __name__ == "__main__":
110
+ serve(reload_excludes=["./app.css"])
uv.lock CHANGED
@@ -564,7 +564,7 @@ dev = [
564
  ]
565
 
566
  [package.metadata]
567
- requires-dist = [{ name = "python-fasthtml", specifier = ">=0.4.5" }]
568
 
569
  [package.metadata.requires-dev]
570
  dev = [{ name = "ruff", specifier = ">=0.6.3" }]
 
564
  ]
565
 
566
  [package.metadata]
567
+ requires-dist = [{ name = "python-fasthtml", specifier = ">=0.4.6" }]
568
 
569
  [package.metadata.requires-dev]
570
  dev = [{ name = "ruff", specifier = ">=0.6.3" }]