ftiiii commited on
Commit
7288094
·
verified ·
1 Parent(s): 4541f89

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +70 -58
app.py CHANGED
@@ -5,7 +5,7 @@ import random
5
  state = {
6
  "score_a": 0,
7
  "score_b": 0,
8
- "turn": "A", # lượt đội A hoặc B
9
  "round": 1,
10
  "total_rounds": 5
11
  }
@@ -33,24 +33,29 @@ def draw_scene(keeper_pos="giữa", ball_dir="giữa", is_goal=True, reset=False
33
  "phải": "translate(180px, -50px)"
34
  }[ball_dir]
35
 
36
- # màu áo cầu thủ và số áo theo đội
37
- if state["turn"]=="A":
38
- shirt_color="#2196F3"
39
- pants_color="#1565C0"
40
- player_number="7"
41
- player_name="Ronaldo"
42
- keeper_shirt="#FFEB3B"
43
- keeper_pants="#FBC02D"
44
  else:
45
- shirt_color="#e53935"
46
- pants_color="#b71c1c"
47
- player_number="10"
48
- player_name="Messi"
49
- keeper_shirt="#FFFFFF"
50
- keeper_pants="#E0E0E0"
51
-
52
- # Nếu có champion: stickman nâng cúp
53
  if champion:
 
 
 
 
 
54
  html = f"""
55
  <div style="position:relative;width:100%;height:360px;background:linear-gradient(#4CAF50,#2e7d32);border-radius:20px;overflow:hidden;">
56
  <div style="position:absolute;bottom:30px;left:50%;transform:translateX(-50%);text-align:center;">
@@ -58,15 +63,18 @@ def draw_scene(keeper_pos="giữa", ball_dir="giữa", is_goal=True, reset=False
58
  <div style="width:20px;height:60px;background:gold;margin:auto;border-radius:4px 4px 0 0;position:relative;">
59
  <div style="width:40px;height:15px;background:gold;position:absolute;top:-15px;left:-10px;border-radius:50%;"></div>
60
  </div>
61
- <!-- Stickman nâng cúp -->
62
- <div style="position:relative;width:60px;height:120px;margin:auto;">
63
- <div style='width:18px;height:18px;background:#ffd1a4;border-radius:50%;position:absolute;top:0;left:50%;transform:translateX(-50%);'></div>
64
- <div style='width:6px;height:50px;background:{shirt_color};position:absolute;top:18px;left:50%;transform:translateX(-50%);'></div>
65
- <div style='width:6px;height:40px;background:{shirt_color};position:absolute;top:18px;left:-10px;transform:rotate(-60deg);'></div>
66
- <div style='width:6px;height:40px;background:{shirt_color};position:absolute;top:18px;right:-10px;transform:rotate(60deg);'></div>
67
- <div style='width:6px;height:40px;background:{pants_color};position:absolute;top:68px;left:15%;transform:rotate(20deg);'></div>
68
- <div style='width:6px;height:40px;background:{pants_color};position:absolute;top:68px;right:15%;transform:rotate(-20deg);'></div>
69
- <div style='position:absolute;top:30px;left:50%;transform:translateX(-50%);color:white;font-weight:bold;font-family:sans-serif;font-size:14px;'>{player_number}</div>
 
 
 
70
  </div>
71
  <div style="margin-top:5px;font-weight:bold;color:white;font-family:sans-serif;">{player_name} vô địch!</div>
72
  </div>
@@ -74,7 +82,7 @@ def draw_scene(keeper_pos="giữa", ball_dir="giữa", is_goal=True, reset=False
74
  """
75
  return html
76
 
77
- # stickman bình thường đá penalty
78
  html = f"""
79
  <div style="position:relative;width:100%;height:360px;background:linear-gradient(#4CAF50,#2e7d32);border-radius:20px;overflow:hidden;">
80
  <!-- Khung thành -->
@@ -87,16 +95,29 @@ def draw_scene(keeper_pos="giữa", ball_dir="giữa", is_goal=True, reset=False
87
  <div style="position:absolute;top:120px;left:50%;transform:{keeper_move[keeper_pos]};transition: all 0.4s ease;">
88
  <div style="width:18px;height:18px;background:#ffd1a4;border-radius:50%;margin:auto;"></div>
89
  <div style="width:30px;height:45px;background:{keeper_shirt};border-radius:8px;margin:auto;"></div>
 
 
 
 
 
 
 
 
90
  </div>
91
  <!-- Cầu thủ -->
92
- <div style="position:absolute;bottom:30px;left:50%;transform:translateX(-50%);">
93
- <div style='width:18px;height:18px;background:#ffd1a4;border-radius:50%;margin:auto;'></div>
94
- <div style='width:6px;height:50px;background:{shirt_color};position:absolute;top:18px;left:50%;transform:translateX(-50%);'></div>
95
- <div style='width:6px;height:40px;background:{shirt_color};position:absolute;top:18px;left:-10px;transform:rotate(20deg);'></div>
96
- <div style='width:6px;height:40px;background:{shirt_color};position:absolute;top:18px;right:-10px;transform:rotate(-20deg);'></div>
97
- <div style='width:6px;height:40px;background:{pants_color};position:absolute;top:68px;left:-10px;transform:rotate(20deg);'></div>
98
- <div style='width:6px;height:40px;background:{pants_color};position:absolute;top:68px;right:-10px;transform:rotate(-20deg);'></div>
99
- <div style='position:absolute;top:0;left:50%;transform:translateX(-50%);color:white;font-weight:bold;font-family:sans-serif;font-size:14px;'>{player_number}</div>
 
 
 
 
 
100
  </div>
101
  <!-- Bóng -->
102
  <div style="position:absolute;bottom:90px;left:50%;width:14px;height:14px;background:white;border-radius:50%;
@@ -111,55 +132,47 @@ def draw_scene(keeper_pos="giữa", ball_dir="giữa", is_goal=True, reset=False
111
  """
112
  return html
113
 
114
- # Sút penalty
115
  def shoot_penalty(direction):
116
  keeper = random.choice(["trái","giữa","phải"])
117
  hit = direction != keeper
118
  return keeper, hit
119
 
120
- # xử lý lượt đá
121
  def next_turn(direction):
122
  keeper, hit = shoot_penalty(direction)
123
- if state["turn"]=="A" and hit: state["score_a"] +=1
124
- if state["turn"]=="B" and hit: state["score_b"] +=1
125
  msg = f"Đội {state['turn']} sút {direction}, thủ môn đoán {keeper} → "
126
  msg += "⚽ Bàn thắng!" if hit else "🧤 Cản phá, bóng dính thủ môn!"
127
  scene = draw_scene(keeper, direction, hit)
128
  return msg, scene
129
 
130
- # Chuẩn bị lượt tiếp theo
131
  def prepare_next_turn():
132
  state["turn"] = "B" if state["turn"]=="A" else "A"
133
- if state["turn"]=="A":
134
- state["round"] +=1
135
-
136
- # kiểm tra kết thúc
 
137
  if state["round"] > state["total_rounds"]:
138
  if state["score_a"] > state["score_b"]:
139
- scene = draw_scene(champion="A")
140
  msg_end = f"🏆 Đội A thắng {state['score_a']} - {state['score_b']}!"
 
141
  elif state["score_b"] > state["score_a"]:
142
- scene = draw_scene(champion="B")
143
  msg_end = f"🏆 Đội B thắng {state['score_b']} - {state['score_a']}!"
 
144
  else:
145
- scene = draw_scene(champion="A") # đội A mặc định nâng cúp khi hòa
146
  msg_end = f"🤝 Hòa {state['score_a']} - {state['score_b']}!"
147
- score_text_val = f"**Điểm A: {state['score_a']} | Điểm B: {state['score_b']} | Lượt: 5/5**"
148
- return score_text_val, scene, msg_end
149
-
150
- scene_reset = draw_scene(reset=True)
151
- score_text_val = f"**Điểm A: {state['score_a']} | Điểm B: {state['score_b']} | Lượt: {min(state['round'],5)}/5**"
152
- return score_text_val, scene_reset, ""
153
 
154
- # Reset game
155
  def reset_game():
156
  state.update({"score_a":0,"score_b":0,"turn":"A","round":1})
157
  scene = draw_scene(reset=True)
158
  return "**Điểm A: 0 | Điểm B: 0 | Lượt: 1/5**", scene, "Game mới bắt đầu! Đội A sút trước."
159
 
160
- # Gradio interface
161
  with gr.Blocks() as demo:
162
- gr.Markdown("# ⚽ Penalty 2 Đội 5 lượt + Stickman + địch nâng cúp")
163
 
164
  score_text = gr.Markdown("**Điểm A: 0 | Điểm B: 0 | Lượt: 1/5**")
165
  result = gr.Markdown("Chọn hướng sút 👇")
@@ -169,10 +182,9 @@ with gr.Blocks() as demo:
169
  btn_left = gr.Button("⬅️ Trái")
170
  btn_center = gr.Button("⬆️ Giữa")
171
  btn_right = gr.Button("➡️ Phải")
172
- btn_next = gr.Button("➡️ Tiếp theo") # reset tư thế chuẩn bị lượt tiếp theo
173
  btn_restart = gr.Button("🔄 Chơi lại")
174
 
175
- # sự kiện
176
  btn_left.click(lambda _: next_turn("trái"), inputs=None, outputs=[result, field])
177
  btn_center.click(lambda _: next_turn("giữa"), inputs=None, outputs=[result, field])
178
  btn_right.click(lambda _: next_turn("phải"), inputs=None, outputs=[result, field])
 
5
  state = {
6
  "score_a": 0,
7
  "score_b": 0,
8
+ "turn": "A",
9
  "round": 1,
10
  "total_rounds": 5
11
  }
 
33
  "phải": "translate(180px, -50px)"
34
  }[ball_dir]
35
 
36
+ # Chọn màu áo và số cầu thủ
37
+ if state["turn"] == "A":
38
+ shirt_color = "#2196F3"
39
+ pants_color = "#1565C0"
40
+ keeper_shirt = "#FFEB3B"
41
+ keeper_pants = "#FBC02D"
42
+ player_number = "7"
43
+ player_name = "Ronaldo"
44
  else:
45
+ shirt_color = "#e53935"
46
+ pants_color = "#b71c1c"
47
+ keeper_shirt = "#FFFFFF"
48
+ keeper_pants = "#E0E0E0"
49
+ player_number = "10"
50
+ player_name = "Messi"
51
+
52
+ # Nếu có champion, vẽ cầu thủ nâng cúp
53
  if champion:
54
+ # màu áo và số theo đội vô địch
55
+ shirt_color = "#2196F3" if champion=="A" else "#e53935"
56
+ pants_color = "#1565C0" if champion=="A" else "#b71c1c"
57
+ player_number = "7" if champion=="A" else "10"
58
+ player_name = "Ronaldo" if champion=="A" else "Messi"
59
  html = f"""
60
  <div style="position:relative;width:100%;height:360px;background:linear-gradient(#4CAF50,#2e7d32);border-radius:20px;overflow:hidden;">
61
  <div style="position:absolute;bottom:30px;left:50%;transform:translateX(-50%);text-align:center;">
 
63
  <div style="width:20px;height:60px;background:gold;margin:auto;border-radius:4px 4px 0 0;position:relative;">
64
  <div style="width:40px;height:15px;background:gold;position:absolute;top:-15px;left:-10px;border-radius:50%;"></div>
65
  </div>
66
+ <!-- Cầu thủ -->
67
+ <div style="width:18px;height:18px;background:#ffd1a4;border-radius:50%;margin:auto;"></div>
68
+ <div style="width:30px;height:45px;background:{shirt_color};border-radius:8px;margin:auto;position:relative;">
69
+ <span style="position:absolute;top:5px;left:50%;transform:translateX(-50%);color:white;font-weight:bold;font-family:sans-serif;font-size:18px;">{player_number}</span>
70
+ </div>
71
+ <div style="display:flex;justify-content:space-between;margin-top:2px;">
72
+ <div style="width:8px;height:25px;background:{shirt_color};transform:rotate(20deg);"></div>
73
+ <div style="width:8px;height:25px;background:{shirt_color};transform:rotate(-20deg);"></div>
74
+ </div>
75
+ <div style="display:flex;justify-content:space-between;">
76
+ <div style="width:8px;height:25px;background:{pants_color};"></div>
77
+ <div style="width:8px;height:25px;background:{pants_color};"></div>
78
  </div>
79
  <div style="margin-top:5px;font-weight:bold;color:white;font-family:sans-serif;">{player_name} vô địch!</div>
80
  </div>
 
82
  """
83
  return html
84
 
85
+ # Nếu không phải champion, vẽ sân bình thường
86
  html = f"""
87
  <div style="position:relative;width:100%;height:360px;background:linear-gradient(#4CAF50,#2e7d32);border-radius:20px;overflow:hidden;">
88
  <!-- Khung thành -->
 
95
  <div style="position:absolute;top:120px;left:50%;transform:{keeper_move[keeper_pos]};transition: all 0.4s ease;">
96
  <div style="width:18px;height:18px;background:#ffd1a4;border-radius:50%;margin:auto;"></div>
97
  <div style="width:30px;height:45px;background:{keeper_shirt};border-radius:8px;margin:auto;"></div>
98
+ <div style="display:flex;justify-content:space-between;">
99
+ <div style="width:8px;height:25px;background:{keeper_shirt};transform:rotate(30deg);"></div>
100
+ <div style="width:8px;height:25px;background:{keeper_shirt};transform:rotate(-30deg);"></div>
101
+ </div>
102
+ <div style="display:flex;justify-content:space-between;">
103
+ <div style="width:8px;height:25px;background:{keeper_pants};"></div>
104
+ <div style="width:8px;height:25px;background:{keeper_pants};"></div>
105
+ </div>
106
  </div>
107
  <!-- Cầu thủ -->
108
+ <div style="position:absolute;bottom:30px;left:50%;transform:translateX(-50%);text-align:center;">
109
+ <div style="width:18px;height:18px;background:#ffd1a4;border-radius:50%;margin:auto;"></div>
110
+ <div style="width:30px;height:45px;background:{shirt_color};border-radius:8px;margin:auto;position:relative;">
111
+ <span style="position:absolute;top:5px;left:50%;transform:translateX(-50%);color:white;font-weight:bold;font-family:sans-serif;font-size:18px;">{player_number}</span>
112
+ </div>
113
+ <div style="display:flex;justify-content:space-between;margin-top:2px;">
114
+ <div style="width:8px;height:25px;background:{shirt_color};transform:rotate(20deg);"></div>
115
+ <div style="width:8px;height:25px;background:{shirt_color};transform:rotate(-20deg);"></div>
116
+ </div>
117
+ <div style="display:flex;justify-content:space-between;">
118
+ <div style="width:8px;height:25px;background:{pants_color};"></div>
119
+ <div style="width:8px;height:25px;background:{pants_color};"></div>
120
+ </div>
121
  </div>
122
  <!-- Bóng -->
123
  <div style="position:absolute;bottom:90px;left:50%;width:14px;height:14px;background:white;border-radius:50%;
 
132
  """
133
  return html
134
 
 
135
  def shoot_penalty(direction):
136
  keeper = random.choice(["trái","giữa","phải"])
137
  hit = direction != keeper
138
  return keeper, hit
139
 
 
140
  def next_turn(direction):
141
  keeper, hit = shoot_penalty(direction)
142
+ if state["turn"] == "A" and hit: state["score_a"] +=1
143
+ if state["turn"] == "B" and hit: state["score_b"] +=1
144
  msg = f"Đội {state['turn']} sút {direction}, thủ môn đoán {keeper} → "
145
  msg += "⚽ Bàn thắng!" if hit else "🧤 Cản phá, bóng dính thủ môn!"
146
  scene = draw_scene(keeper, direction, hit)
147
  return msg, scene
148
 
 
149
  def prepare_next_turn():
150
  state["turn"] = "B" if state["turn"]=="A" else "A"
151
+ if state["turn"]=="A": state["round"] +=1
152
+ score_text_val = f"**Điểm A: {state['score_a']} | Điểm B: {state['score_b']} | Lượt: {min(state['round'],5)}/5**"
153
+ scene_reset = draw_scene(reset=True)
154
+ msg_end = ""
155
+ champion = None
156
  if state["round"] > state["total_rounds"]:
157
  if state["score_a"] > state["score_b"]:
 
158
  msg_end = f"🏆 Đội A thắng {state['score_a']} - {state['score_b']}!"
159
+ champion = "A"
160
  elif state["score_b"] > state["score_a"]:
 
161
  msg_end = f"🏆 Đội B thắng {state['score_b']} - {state['score_a']}!"
162
+ champion = "B"
163
  else:
 
164
  msg_end = f"🤝 Hòa {state['score_a']} - {state['score_b']}!"
165
+ if champion:
166
+ scene_reset = draw_scene(champion=champion)
167
+ return score_text_val, scene_reset, msg_end
 
 
 
168
 
 
169
  def reset_game():
170
  state.update({"score_a":0,"score_b":0,"turn":"A","round":1})
171
  scene = draw_scene(reset=True)
172
  return "**Điểm A: 0 | Điểm B: 0 | Lượt: 1/5**", scene, "Game mới bắt đầu! Đội A sút trước."
173
 
 
174
  with gr.Blocks() as demo:
175
+ gr.Markdown("# ⚽ Penalty – Cầu thủ nâng cúp bằng CSS khi địch")
176
 
177
  score_text = gr.Markdown("**Điểm A: 0 | Điểm B: 0 | Lượt: 1/5**")
178
  result = gr.Markdown("Chọn hướng sút 👇")
 
182
  btn_left = gr.Button("⬅️ Trái")
183
  btn_center = gr.Button("⬆️ Giữa")
184
  btn_right = gr.Button("➡️ Phải")
185
+ btn_next = gr.Button("➡️ Tiếp theo")
186
  btn_restart = gr.Button("🔄 Chơi lại")
187
 
 
188
  btn_left.click(lambda _: next_turn("trái"), inputs=None, outputs=[result, field])
189
  btn_center.click(lambda _: next_turn("giữa"), inputs=None, outputs=[result, field])
190
  btn_right.click(lambda _: next_turn("phải"), inputs=None, outputs=[result, field])