1
0
Эх сурвалжийг харах

add gomoku demo and doc update

wangweimin 3 жил өмнө
parent
commit
2baed9d565

+ 11 - 6
demos/__main__.py

@@ -9,6 +9,7 @@ from demos.config import charts_demo_host
 from demos.doc_demo import get_app as get_doc_demo_app
 from demos.set_env_demo import main as set_env_demo
 from demos.markdown_previewer import main as markdown_previewer
+from demos.gomoku_game import main as gomoku_game
 
 from pywebio import STATIC_PATH
 from pywebio.output import put_markdown, put_row, put_html, style
@@ -19,10 +20,11 @@ from tornado.options import define, options
 index_md = r"""### Basic demo
 
  - [BMI calculation](./bmi): Calculating Body Mass Index based on height and weight
- - [Online chat room](./chat_room): Chat with everyone currently online
- - [Markdown live preview](./markdown_previewer): The online markdown editor with live preview
- - [Input demo](./input_usage): Demonstrate various input usage supported by PyWebIO
- - [Output demo](./output_usage): Demonstrate various output usage supported by PyWebIO
+ - [Online chat room](./chat_room): Chat with everyone currently online (using less than 90 lines of code)
+ - [Markdown live preview](./markdown_previewer): The online markdown editor with live preview (using less than 40 lines of code)
+ - [Online Gomoku game](./gomoku_game): An online shared Gomoku game (using less than 100 lines of code)
+ - [Input demo](./input_usage): Demonstrate the usage of PyWebIO input module 
+ - [Output demo](./output_usage): Demonstrate the usage of PyWebIO output module 
 
 ### Data visualization demo
 PyWebIO supports for data visualization with the third-party libraries.
@@ -61,7 +63,9 @@ PyWebIO supports for data visualization with the third-party libraries.
 index_md_zh = r"""### 基本demo
 
  - [BMI计算](./bmi): 根据身高体重计算BMI指数
- - [聊天室](./chat_room): 和当前所有在线的人聊天
+ - [聊天室](./chat_room): 和当前所有在线的人聊天 (不到90行代码实现)
+ - [Markdown实时预览](./markdown_previewer): 可以实时预览的在线Markdown编辑器 (不到40行代码实现)
+ - [在线五子棋游戏](./gomoku_game): 多人协作对战的五子棋游戏 (不到100行代码实现)
  - [输入演示](./input_usage):  演示PyWebIO输入模块的用法
  - [输出演示](./output_usage): 演示PyWebIO输出模块的用法 
  - 更多Demo请见[文档](https://pywebio.readthedocs.io)中示例代码的在线Demo
@@ -95,7 +99,7 @@ PyWebIO还支持使用第三方库进行数据可视化
 
 ### Links
 * PyWebIO Github [github.com/wang0618/PyWebIO](https://github.com/wang0618/PyWebIO)
-* 使用手册和实现文档见 [pywebio.readthedocs.io](https://pywebio.readthedocs.io)
+* 使用手册和实现文档见 [pywebio.readthedocs.io](https://pywebio.readthedocs.io/zh_CN/latest/)
 
 """.format(charts_demo_host=charts_demo_host)
 
@@ -130,6 +134,7 @@ if __name__ == "__main__":
         (r"/doc_demo", webio_handler(get_doc_demo_app(), cdn=False)),
         (r"/set_env_demo", webio_handler(set_env_demo, cdn=False)),
         (r"/markdown_previewer", webio_handler(markdown_previewer, cdn=False)),
+        (r"/gomoku_game", webio_handler(gomoku_game, cdn=False)),
         (r"/(.*)", tornado.web.StaticFileHandler, {"path": STATIC_PATH, 'default_filename': 'index.html'})
     ])
     application.listen(port=options.port)

+ 98 - 0
demos/gomoku_game.py

@@ -0,0 +1,98 @@
+"""
+Online Shared Gomoku Game
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+All online players are divided into two roles (black and white) and play same Gomoku game together.
+
+:demo_host:`Demo </gomoku_game>`, `Source code <https://github.com/wang0618/PyWebIO/blob/dev/demos/gomoku_game.py>`_
+"""
+import pywebio, time
+from pywebio.output import *
+from pywebio.session import *
+
+chessboard_size = 15
+# -1 -> none, 0 -> black, 1 -> white
+chessboard = [
+    [-1] * chessboard_size
+    for _ in range(chessboard_size)
+]
+
+def winner():  # return winner piece, return None if no winner
+    for x in range(2, chessboard_size - 2):
+        for y in range(2, chessboard_size - 2):
+            # check if (x,y) is the win center
+            if chessboard[x][y] != -1 and any([
+                all(chessboard[x][y] == chessboard[m][n] for m, n in [(x - 2, y), (x - 1, y), (x + 1, y), (x + 2, y)]),
+                all(chessboard[x][y] == chessboard[m][n] for m, n in [(x, y - 2), (x, y - 1), (x, y + 1), (x, y + 2)]),
+                all(chessboard[x][y] == chessboard[m][n] for m, n in [(x - 2, y - 2), (x - 1, y - 1), (x + 1, y + 1), (x + 2, y + 2)]),
+                all(chessboard[x][y] == chessboard[m][n] for m, n in [(x - 2, y + 2), (x - 1, y + 1), (x + 1, y - 1), (x + 2, y - 2)]),
+            ]):
+                return ['⚫', '⚪'][chessboard[x][y]]
+
+session_id = 0          # auto incremented id for each session
+current_turn = 0        # 0 for black, 1 for white
+player_count = [0, 0]   # count of player for two roles
+def main():
+    """Online Shared Gomoku Game
+
+    All online players are divided into two roles (black and white) and share this game."""
+    global session_id, current_turn, chessboard
+    if winner():  # The current game is over, reset game
+        chessboard = [[-1] * chessboard_size for _ in range(chessboard_size)]
+        current_turn = 0
+
+    my_turn = session_id % 2
+    my_chess = ['⚫', '⚪'][my_turn]
+    session_id += 1
+    player_count[my_turn] += 1
+
+    @defer_call
+    def player_exit():
+        player_count[my_turn] -= 1
+
+    set_env(output_animation=False)
+    put_html("""<style> table th, table td { padding: 0px !important;} button {padding: .75rem!important; margin:0!important} </style>""")  # Custom styles to make the board more beautiful
+
+    put_markdown(f"""# Online Shared Gomoku Game
+    All online players are divided into two roles (black and white) and share this game. You can open this page in multiple tabs of your browser to simulate multiple users.
+    This application uses less than 100 lines of code, the source code is [here](https://github.com/wang0618/PyWebIO/blob/dev/demos/gomoku_game.py)
+    Currently online player: {player_count[0]} for ⚫, {player_count[1]} for ⚪.
+    Your role is {my_chess}.
+    """, lstrip=True)
+
+    def set_chess(pos):
+        global current_turn
+        if current_turn != my_turn:
+            toast("It's not your turn!!", color='error')
+            return
+        x, y = pos
+        chessboard[x][y] = my_turn
+        current_turn = (current_turn + 1) % 2
+
+    @use_scope('chessboard', clear=True)
+    def show_chessboard():
+        table = [
+            [
+                put_buttons([dict(label=' ', value=(x, y), color='light')], onclick=set_chess) if cell == -1 else [' ⚫', ' ⚪'][cell]
+                for y, cell in enumerate(row)
+            ]
+            for x, row in enumerate(chessboard)
+        ]
+        put_table(table)
+
+    show_chessboard()
+    while not winner():
+        with use_scope('msg', clear=True):
+            current_turn_copy = current_turn
+            if current_turn_copy == my_turn:
+                put_text("It's your turn!")
+            else:
+                put_row([put_text("Your opponent's turn, waiting... "), put_loading().style('width:1.5em; height:1.5em')], size='auto 1fr')
+            while current_turn == current_turn_copy:  # wait for next move
+                time.sleep(0.2)
+            show_chessboard()
+    with use_scope('msg', clear=True):
+        put_text('Game over. The winner is %s!\nRefresh page to start a new round.' % winner())
+
+
+if __name__ == '__main__':
+    pywebio.start_server(main, debug=True, port=8080, cdn=False)

+ 3 - 3
docs/locales/zh_CN/LC_MESSAGES/demos.po

@@ -8,7 +8,7 @@ msgstr ""
 "Project-Id-Version: PyWebIO 1.1.0\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2021-05-30 17:09+0800\n"
-"PO-Revision-Date: 2021-05-30 17:09+0800\n"
+"PO-Revision-Date: 2021-07-17 17:17+0800\n"
 "Last-Translator: WangWeimin <wang0.618@qq.com>\n"
 "Language: zh_CN\n"
 "Language-Team: \n"
@@ -17,7 +17,7 @@ msgstr ""
 "Content-Type: text/plain; charset=utf-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Generated-By: Babel 2.8.0\n"
-"X-Generator: Poedit 2.4.2\n"
+"X-Generator: Poedit 3.0\n"
 
 #: ../../demos.rst:2
 msgid "Demos"
@@ -119,7 +119,7 @@ msgid ""
 "wang0618/PyWebIO/blob/dev/demos/markdown_previewer.py>`_"
 msgstr ""
 ":demo_host:`Demo地址 </markdown_previewer>`, `源码 <https://github.com/wang0618/"
-"PyWebIO/blob/dev/demos/bmi.py>`_"
+"PyWebIO/blob/dev/demos/markdown_previewer.py>`_"
 
 #: ../../demos.rst:11
 msgid "Data visualization demos"

+ 1 - 1
pywebio/output.py

@@ -912,7 +912,7 @@ def put_loading(shape='border', color='dark', scope=Scope.Current, position=Outp
 
         ## ----
         # using style() to set the size of the loading prompt
-        style(put_loading(), 'width:4rem; height:4rem')
+        put_loading().style('width:4rem; height:4rem')
     """
     assert shape in ('border', 'grow'), "shape must in ('border', 'grow')"
     assert color in {'primary', 'secondary', 'success', 'danger', 'warning', 'info', 'light', 'dark'}

+ 1 - 1
pywebio/session/__init__.py

@@ -487,7 +487,7 @@ def set_env(**env_info):
     * ``input_panel_min_height`` (int): The minimum height of input panel (in pixel, default 300px), it should be larger than 75px. Available only when ``input_panel_fixed=True``
     * ``input_panel_init_height`` (int): The initial height of input panel (in pixel, default 300px), it should be larger than 175px. Available only when ``input_panel_fixed=True``
     * ``input_auto_focus`` (bool): Whether to focus on input automatically after showing input panel, default is ``True``
-    * ``output_max_width`` (str): The max width of the page content area (in pixel or percentage, e.g. ``'1080px'``,``80%``. Default is 880px).
+    * ``output_max_width`` (str): The max width of the page content area (in pixel or percentage, e.g. ``'1080px'``, ``'80%'``. Default is 880px).
 
     Example::