nonebot-plugin-fishing2 0.0.2__py3-none-any.whl → 0.0.4__py3-none-any.whl

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.
@@ -7,46 +7,150 @@ import json
7
7
  from typing import Union
8
8
  from sqlalchemy import select, update, delete
9
9
  from sqlalchemy.sql.expression import func
10
+ from nonebot.adapters.onebot.v11 import MessageSegment
10
11
  from nonebot_plugin_orm import get_session
11
12
 
12
13
  from .config import config
13
14
  from .model import FishingRecord, SpecialFishes
15
+ from .fish_helper import *
14
16
 
15
- fishing_coin_name = config.fishing_coin_name
16
- fish_list = [fish["name"] for fish in config.fishes]
17
- can_catch_fishes = {fish["name"]: fish["weight"] for fish in config.fishes if fish["can_catch"]}
18
- can_buy_fishes = [fish["name"] for fish in config.fishes if fish["can_catch"]]
19
- can_sell_fishes = [fish["name"] for fish in config.fishes if fish["can_sell"]]
20
17
 
21
- def adjusted_choice(adjusts: list[dict[str, Union[str, int]]] = None) -> str:
18
+ async def can_fishing(user_id: str) -> bool:
19
+ time_now = int(time.time())
20
+ session = get_session()
21
+ async with session.begin():
22
+ select_user = select(FishingRecord).where(FishingRecord.user_id == user_id)
23
+ record = await session.scalar(select_user)
24
+ return True if not record else record.time < time_now
25
+
26
+
27
+ async def can_catch_special_fish(probability_add: int):
28
+ session = get_session()
29
+ async with session.begin():
30
+ records = await session.execute(select(SpecialFishes))
31
+ return (
32
+ len(records.all()) != 0
33
+ and random.random() <= config.special_fish_probability + probability_add
34
+ )
35
+
36
+
37
+ async def check_tools(
38
+ user_id: str, tools: list[str] = None, check_have: bool = True
39
+ ) -> str | None:
40
+ if not tools or tools == []:
41
+ return None
42
+
43
+ # 这是工具吗?
44
+ for tool in tools:
45
+ fish = get_fish_by_name(tool)
46
+ if not fish:
47
+ return f"你在用什么钓鱼……?{tool}?"
48
+
49
+ props = fish.props
50
+ if not props or props == []:
51
+ return f"搞啥嘞!{tool}既不是工具也不是鱼饵!"
52
+
53
+ # 如果有两个工具,是一个工具一个鱼饵吗?
54
+ if len(tools) == 2:
55
+ if get_fish_by_name(tools[0]).type == get_fish_by_name(tools[1]).type:
56
+ return "你为啥要用两个类型一样的东西?"
57
+
58
+ # 有吗?有吗?
59
+ if check_have:
60
+ session = get_session()
61
+ async with session.begin():
62
+ select_user = select(FishingRecord).where(FishingRecord.user_id == user_id)
63
+ fishes_record = await session.scalar(select_user)
64
+ if fishes_record:
65
+ loads_fishes = json.loads(fishes_record.fishes)
66
+ for tool in tools:
67
+ if tool not in loads_fishes:
68
+ return f"你哪来的{tool}?"
69
+
70
+ return None
22
71
 
72
+
73
+ async def remove_tools(user_id: str, tools: list[str] = None) -> None:
74
+ if not tools or tools == []:
75
+ return None
76
+
77
+ session = get_session()
78
+ async with session.begin():
79
+ select_user = select(FishingRecord).where(FishingRecord.user_id == user_id)
80
+ fishes_record = await session.scalar(select_user)
81
+ if fishes_record:
82
+ loads_fishes = json.loads(fishes_record.fishes)
83
+ for tool_name in tools:
84
+ loads_fishes[tool_name] -= 1
85
+ if loads_fishes[tool_name] == 0:
86
+ del loads_fishes[tool_name]
87
+ dump_fishes = json.dumps(loads_fishes)
88
+ user_update = (
89
+ update(FishingRecord)
90
+ .where(FishingRecord.user_id == user_id)
91
+ .values(fishes=dump_fishes)
92
+ )
93
+ await session.execute(user_update)
94
+ await session.commit()
95
+ else:
96
+ pass
97
+ # raise ValueError("?你的 Check 是怎么通过的?")
98
+
99
+
100
+ def get_adjusts_from_tools(tools: list = None) -> list:
101
+ no_add = 0
102
+ sp_add = 0
103
+ adjusts: list[Property] = []
104
+
105
+ if tools:
106
+ for tool in tools:
107
+ adjusts += get_fish_by_name(tool).props
108
+
109
+ for adjust in adjusts:
110
+ if adjust.type == "special_fish":
111
+ sp_add += adjust.value
112
+ if adjust.type == "no_fish":
113
+ no_add += adjust.value
114
+
115
+ return adjusts, no_add, sp_add
116
+
117
+
118
+ def adjusted(adjusts: list[Property] = None) -> tuple:
23
119
  adjusted_fishes = copy.deepcopy(can_catch_fishes)
24
-
25
- if adjusts:
26
- for adjust in adjusts:
27
- if adjust.get("key") and adjust["key"] not in adjusted_fishes:
28
- continue
29
- match adjust["type"]:
30
- case "normal_fish":
31
- for key, weight in can_catch_fishes:
32
- if weight >= 500 and key in adjusted_fishes:
33
- adjusted_fishes[key] += adjust["value"]
34
- case "rare_fish":
35
- for key, weight in can_catch_fishes:
36
- if weight < 500 and key in adjusted_fishes:
37
- adjusted_fishes[key] += adjust["value"]
38
- case "fish":
39
- adjusted_fishes[adjust["key"]] += adjust["value"]
40
- case "rm_fish":
41
- adjusted_fishes.pop(adjust["key"])
42
- case "special_fish":
43
- pass
44
- case _:
45
- pass
46
-
120
+
121
+ for adjust in adjusts:
122
+ if adjust.key and adjust.key not in adjusted_fishes:
123
+ continue
124
+ match adjust.type:
125
+ case "normal_fish":
126
+ for key, weight in can_catch_fishes.items():
127
+ if weight >= config.rare_fish_weight and key in adjusted_fishes:
128
+ adjusted_fishes[key] += adjust.value
129
+ case "rare_fish":
130
+ for key, weight in can_catch_fishes.items():
131
+ if weight < config.rare_fish_weight and key in adjusted_fishes:
132
+ adjusted_fishes[key] += adjust.value
133
+ case "fish":
134
+ adjusted_fishes[adjust.key] += adjust.value
135
+ case "rm_fish":
136
+ adjusted_fishes.pop(adjust.key)
137
+ case "special_fish" | "no_fish":
138
+ pass
139
+ case _:
140
+ pass
141
+
47
142
  adjusted_fishes_list = list(adjusted_fishes.keys())
48
143
  adjusted_weights = list(adjusted_fishes.values())
49
-
144
+
145
+ for i in range(len(adjusted_weights)):
146
+ if adjusted_weights[i] < 0:
147
+ adjusted_weights[i] = 0
148
+
149
+ return adjusted_fishes_list, adjusted_weights
150
+
151
+
152
+ def choice(adjusts: list[Property] = None) -> str:
153
+ adjusted_fishes_list, adjusted_weights = adjusted(adjusts)
50
154
  choices = random.choices(
51
155
  adjusted_fishes_list,
52
156
  weights=adjusted_weights,
@@ -55,80 +159,67 @@ def adjusted_choice(adjusts: list[dict[str, Union[str, int]]] = None) -> str:
55
159
 
56
160
 
57
161
  async def get_fish(user_id: int, tools: list = None) -> str:
58
- probability_add = 0
59
- adjusts: list[dict[str, Union[str, int]]] = []
60
-
61
- if tools:
62
- for tool in tools:
63
- adjusts += get_props(tool)
162
+ adjusts, no_add, sp_add = get_adjusts_from_tools(tools)
64
163
 
65
- for adjust in adjusts:
66
- if adjust["type"] == "special_fish":
67
- probability_add += adjust["value"]
68
-
69
- if await can_catch_special_fish(probability_add):
164
+ if random.random() < config.no_fish_probability + no_add:
165
+ await asyncio.sleep(random.randint(10, 20))
166
+ return "QAQ你空军了,什么都没钓到"
167
+
168
+ if await can_catch_special_fish(sp_add):
70
169
  special_fish_name = await random_get_a_special_fish()
170
+ await asyncio.sleep(random.randint(10, 20))
71
171
  await save_special_fish(user_id, special_fish_name)
72
172
  result = f"你钓到了别人放生的 {special_fish_name}"
73
173
  return result
74
- fish = adjusted_choice(adjusts)
75
- sleep_time = get_frequency(fish)
174
+
175
+ fish = choice(adjusts)
176
+ sleep_time = get_fish_by_name(fish).sleep_time
76
177
  result = f"钓到了一条{fish}, 你把它收进了背包里"
77
178
  await asyncio.sleep(sleep_time)
78
179
  await save_fish(user_id, fish)
79
180
  return result
80
181
 
81
182
 
82
- def get_type(fish_name: str) -> list:
83
- """获取鱼的类型"""
84
- config_fishes = config.fishes
85
- return next(
86
- (
87
- fish["type"]
88
- for fish in config_fishes
89
- if fish["name"] == fish_name
90
- ),
91
- "fish"
92
- )
183
+ def predict(tools: list = None) -> str:
184
+ no = config.no_fish_probability
185
+ sp = config.special_fish_probability
186
+ sp_price = config.special_fish_price
187
+ result = ""
93
188
 
94
- def get_props(fish_name: str) -> list:
95
- """获取鱼的属性"""
96
- config_fishes = config.fishes
97
- return next(
98
- (
99
- fish["props"]
100
- for fish in config_fishes
101
- if fish["name"] == fish_name
102
- ),
103
- []
104
- )
105
- def get_price(fish_name: str) -> int:
106
- """获取鱼的价格"""
107
- config_fishes = config.fishes
108
- return next(
109
- (
110
- fish["price"]
111
- for fish in config_fishes
112
- if fish["name"] == fish_name
113
- ),
114
- 0
115
- )
116
-
117
- def get_frequency(fish_name: str) -> int:
118
- """获取鱼的冷却"""
119
- config_fishes = config.fishes
120
- return next(
121
- (
122
- fish["frequency"]
123
- for fish in config_fishes
124
- if fish["name"] == fish_name
125
- ),
126
- 60
127
- )
189
+ adjusts, no_add, sp_add = get_adjusts_from_tools(tools)
190
+ sp_t = min(max(sp + sp_add, 0), 1)
191
+ no_t = min(max(no + no_add, 0), 1)
192
+
193
+ # 拉取矫正权重
194
+ adjusted_fishes_list, adjusted_weights = adjusted(adjusts)
195
+
196
+ adjusted_fishes_value = []
197
+ for fish_name in adjusted_fishes_list:
198
+ fish = get_fish_by_name(fish_name)
199
+ adjusted_fishes_value.append(int(fish.price * fish.amount))
200
+
201
+ # 归一化
202
+ total_weight = sum(adjusted_weights)
203
+ probabilities = [w / total_weight for w in adjusted_weights]
204
+ expected_value = sum(v * p for v, p in zip(adjusted_fishes_value, probabilities))
205
+
206
+ result += f"鱼列表:[{', '.join(adjusted_fishes_list)}]\n"
207
+ result += f"概率列表: [{', '.join([str(round(w * 100, 2)) + "%" for w in probabilities])}]\n"
208
+ result += f"特殊鱼概率:{round(sp_t * (1 - no_t), 6)}\n"
209
+ result += f"空军概率:{round(no_t, 6)}\n"
210
+
211
+ # 无特殊鱼
212
+ expected_value = expected_value * (1 - no_t)
213
+ result += f"无特殊鱼时期望为:{expected_value:.3f}\n"
214
+
215
+ # 有特殊鱼
216
+ expected_value = expected_value * (1 - sp_t) + sp_price * sp_t * (1 - no_t)
217
+ result += f"有特殊鱼期望为:{expected_value:.3f}"
218
+
219
+ return result
128
220
 
129
221
 
130
222
  async def random_get_a_special_fish() -> str:
131
- """随机返回一条别人放生的鱼"""
132
223
  session = get_session()
133
224
  async with session.begin():
134
225
  random_select = select(SpecialFishes).order_by(func.random())
@@ -136,38 +227,39 @@ async def random_get_a_special_fish() -> str:
136
227
  return data.fish
137
228
 
138
229
 
139
- async def can_fishing(user_id: str) -> bool:
140
- """判断是否可以钓鱼"""
141
- time_now = int(time.time())
230
+ async def get_all_special_fish() -> list[str]:
142
231
  session = get_session()
143
232
  async with session.begin():
144
- select_user = select(FishingRecord).where(FishingRecord.user_id == user_id)
145
- record = await session.scalar(select_user)
146
- return True if not record else record.time < time_now
147
-
148
-
149
- def can_free_fish() -> bool:
150
- return config.special_fish_enabled
233
+ random_select = select(SpecialFishes.fish).order_by(SpecialFishes.fish.asc())
234
+ data = await session.scalars(random_select)
235
+ result = data.all()
236
+ return result
151
237
 
152
238
 
153
239
  async def check_achievement(user_id: str) -> str | None:
154
240
  session = get_session()
155
241
  async with session.begin():
156
- record = await session.scalar(select(FishingRecord).where(FishingRecord.user_id == user_id))
242
+ record = await session.scalar(
243
+ select(FishingRecord).where(FishingRecord.user_id == user_id)
244
+ )
157
245
  if not record:
158
246
  return None
159
247
  fishing_frequency = record.frequency
160
248
  user_fishes = json.loads(record.fishes)
161
- achievements = config.fishing_achievement
249
+ achievements = config_achievements
162
250
  result_list = []
163
251
  for achievement in achievements:
164
- achievement_name = achievement["name"]
252
+ achievement_name = achievement.name
165
253
  if await is_exists_achievement(user_id, achievement_name):
166
254
  continue
167
- if (achievement["type"] == "fishing_frequency" and achievement["data"] <= fishing_frequency) or \
168
- (achievement["type"] == "fish_type" and achievement["data"] in user_fishes):
255
+ if (
256
+ achievement.type == "fishing_frequency"
257
+ and achievement.data <= fishing_frequency
258
+ ) or (achievement.type == "fish_type" and achievement.data in user_fishes):
169
259
  await save_achievement(user_id, achievement_name)
170
- result_list.append(f"""达成成就: {achievement_name}\n{achievement["description"]}""")
260
+ result_list.append(
261
+ f"""达成成就: {achievement_name}\n{achievement.description}"""
262
+ )
171
263
  return result_list if result_list != [] else None
172
264
 
173
265
 
@@ -192,10 +284,10 @@ async def save_achievement(user_id: str, achievement_name: str):
192
284
  loads_achievements = json.loads(record.achievements)
193
285
  loads_achievements.append(achievement_name)
194
286
  dump_achievements = json.dumps(loads_achievements)
195
- user_update = update(FishingRecord).where(
196
- FishingRecord.user_id == user_id
197
- ).values(
198
- achievements=dump_achievements
287
+ user_update = (
288
+ update(FishingRecord)
289
+ .where(FishingRecord.user_id == user_id)
290
+ .values(achievements=dump_achievements)
199
291
  )
200
292
  await session.execute(user_update)
201
293
  await session.commit()
@@ -209,16 +301,16 @@ async def save_achievement(user_id: str, achievement_name: str):
209
301
  fishes="{}",
210
302
  special_fishes="{}",
211
303
  coin=0,
212
- achievements=dump_achievements
304
+ achievements=dump_achievements,
213
305
  )
214
306
  session.add(new_record)
215
307
  await session.commit()
216
308
 
217
309
 
218
310
  async def save_fish(user_id: str, fish_name: str) -> None:
219
- """向数据库写入鱼以持久化保存"""
220
311
  time_now = int(time.time())
221
312
  fishing_limit = config.fishing_limit
313
+ amount = get_fish_by_name(fish_name).amount
222
314
  session = get_session()
223
315
  async with session.begin():
224
316
  select_user = select(FishingRecord).where(FishingRecord.user_id == user_id)
@@ -226,24 +318,24 @@ async def save_fish(user_id: str, fish_name: str) -> None:
226
318
  if record:
227
319
  loads_fishes = json.loads(record.fishes)
228
320
  try:
229
- loads_fishes[fish_name] += 1
321
+ loads_fishes[fish_name] += amount
230
322
  except KeyError:
231
- loads_fishes[fish_name] = 1
323
+ loads_fishes[fish_name] = amount
232
324
  dump_fishes = json.dumps(loads_fishes)
233
325
  new_frequency = record.frequency + 1
234
- user_update = update(FishingRecord).where(
235
- FishingRecord.user_id == user_id
236
- ).values(
237
- time=time_now + fishing_limit,
238
- frequency=new_frequency,
239
- fishes=dump_fishes
326
+ user_update = (
327
+ update(FishingRecord)
328
+ .where(FishingRecord.user_id == user_id)
329
+ .values(
330
+ time=time_now + fishing_limit,
331
+ frequency=new_frequency,
332
+ fishes=dump_fishes,
333
+ )
240
334
  )
241
335
  await session.execute(user_update)
242
336
  await session.commit()
243
337
  return
244
- data = {
245
- fish_name: 1
246
- }
338
+ data = {fish_name: amount}
247
339
  dump_fishes = json.dumps(data)
248
340
  new_record = FishingRecord(
249
341
  user_id=user_id,
@@ -252,19 +344,12 @@ async def save_fish(user_id: str, fish_name: str) -> None:
252
344
  fishes=dump_fishes,
253
345
  special_fishes="{}",
254
346
  coin=0,
255
- achievements="[]"
347
+ achievements="[]",
256
348
  )
257
349
  session.add(new_record)
258
350
  await session.commit()
259
351
 
260
352
 
261
- async def can_catch_special_fish(probability_add: int):
262
- session = get_session()
263
- async with session.begin():
264
- records = await session.execute(select(SpecialFishes))
265
- return len(records.all()) != 0 and random.random() <= config.special_fish_probability + probability_add
266
-
267
-
268
353
  async def save_special_fish(user_id: str, fish_name: str) -> None:
269
354
  time_now = int(time.time())
270
355
  fishing_limit = config.fishing_limit
@@ -279,18 +364,18 @@ async def save_special_fish(user_id: str, fish_name: str) -> None:
279
364
  except KeyError:
280
365
  loads_fishes[fish_name] = 1
281
366
  dump_fishes = json.dumps(loads_fishes)
282
- user_update = update(FishingRecord).where(
283
- FishingRecord.user_id == user_id
284
- ).values(
285
- time=time_now + fishing_limit,
286
- frequency=record.frequency + 1,
287
- special_fishes=dump_fishes
367
+ user_update = (
368
+ update(FishingRecord)
369
+ .where(FishingRecord.user_id == user_id)
370
+ .values(
371
+ time=time_now + fishing_limit,
372
+ frequency=record.frequency + 1,
373
+ special_fishes=dump_fishes,
374
+ )
288
375
  )
289
376
  await session.execute(user_update)
290
377
  else:
291
- data = {
292
- fish_name: 1
293
- }
378
+ data = {fish_name: 1}
294
379
  dump_fishes = json.dumps(data)
295
380
  new_record = FishingRecord(
296
381
  user_id=user_id,
@@ -299,12 +384,15 @@ async def save_special_fish(user_id: str, fish_name: str) -> None:
299
384
  fishes="{}",
300
385
  special_fishes=dump_fishes,
301
386
  coin=0,
302
- achievements=[]
387
+ achievements=[],
303
388
  )
304
389
  session.add(new_record)
305
- select_fish = select(SpecialFishes).where(
306
- SpecialFishes.fish == fish_name
307
- ).order_by(SpecialFishes.id).limit(1)
390
+ select_fish = (
391
+ select(SpecialFishes)
392
+ .where(SpecialFishes.fish == fish_name)
393
+ .order_by(SpecialFishes.id)
394
+ .limit(1)
395
+ )
308
396
  record = await session.scalar(select_fish)
309
397
  fish_id = record.id
310
398
  delete_fishes = delete(SpecialFishes).where(SpecialFishes.id == fish_id)
@@ -312,59 +400,7 @@ async def save_special_fish(user_id: str, fish_name: str) -> None:
312
400
  await session.commit()
313
401
 
314
402
 
315
- async def get_stats(user_id: str) -> str:
316
- """获取钓鱼统计信息"""
317
- session = get_session()
318
- async with session.begin():
319
- select_user = select(FishingRecord).where(FishingRecord.user_id == user_id)
320
- fishing_record = await session.scalar(select_user)
321
- if fishing_record:
322
- return f"🐟你钓鱼了 {fishing_record.frequency} 次"
323
- return "🐟你还没有钓过鱼,快去钓鱼吧"
324
-
325
-
326
- def print_backpack(backpack: dict, special_backpack=None) -> str:
327
- """输出背包内容"""
328
- result = [
329
- f"{fish_name}×{str(quantity)}"
330
- for fish_name, quantity in backpack.items()
331
- ]
332
- if special_backpack:
333
- special_result = [
334
- f"{fish_name}×{str(quantity)}"
335
- for fish_name, quantity in special_backpack.items()
336
- ]
337
- return "🎒背包:\n" + "\n".join(result) + "\n\n特殊鱼:\n" + "\n".join(special_result)
338
- return "🎒背包:\n" + "\n".join(result)
339
-
340
-
341
- async def get_backpack(user_id: str) -> str:
342
- """从数据库查询背包内容"""
343
- session = get_session()
344
- async with session.begin():
345
- select_user = select(FishingRecord).where(FishingRecord.user_id == user_id)
346
- fishes_record = await session.scalar(select_user)
347
- if fishes_record:
348
- load_fishes = json.loads(fishes_record.fishes)
349
- load_special_fishes = json.loads(fishes_record.special_fishes)
350
- if load_special_fishes:
351
- return print_backpack(load_fishes, load_special_fishes)
352
- return "🎒你的背包里空无一物" if load_fishes == {} else print_backpack(load_fishes)
353
- return "🎒你的背包里空无一物"
354
-
355
-
356
403
  async def sell_fish(user_id: str, fish_name: str, quantity: int = 1) -> str:
357
- """
358
- 卖鱼
359
-
360
- 参数:
361
- - user_id: 用户标识符
362
- - fish_name: 将要卖鱼的鱼名称
363
- - quantity: 卖出鱼的数量
364
-
365
- 返回:
366
- - (str): 回复的文本
367
- """
368
404
  if quantity <= 0:
369
405
  return "你在卖什么 w(゚Д゚)w"
370
406
  session = get_session()
@@ -375,25 +411,29 @@ async def sell_fish(user_id: str, fish_name: str, quantity: int = 1) -> str:
375
411
  loads_fishes = json.loads(fishes_record.fishes)
376
412
  spec_fishes = json.loads(fishes_record.special_fishes)
377
413
  if fish_name in loads_fishes and loads_fishes[fish_name] > 0:
378
- fish_price = get_price(fish_name)
379
414
  if fish_name not in can_sell_fishes:
380
415
  return f"这个 {fish_name} 不可以卖哦~"
381
416
  if loads_fishes[fish_name] < quantity:
382
417
  return f"你没有那么多 {fish_name}"
418
+ fish_price = get_fish_by_name(fish_name).price
383
419
  loads_fishes[fish_name] -= quantity
384
420
  if loads_fishes[fish_name] == 0:
385
421
  del loads_fishes[fish_name]
386
422
  dump_fishes = json.dumps(loads_fishes)
387
- user_update = update(FishingRecord).where(
388
- FishingRecord.user_id == user_id
389
- ).values(
390
- coin=fishes_record.coin + fish_price * quantity,
391
- fishes=dump_fishes
423
+ user_update = (
424
+ update(FishingRecord)
425
+ .where(FishingRecord.user_id == user_id)
426
+ .values(
427
+ coin=fishes_record.coin + fish_price * quantity,
428
+ fishes=dump_fishes,
429
+ )
392
430
  )
393
431
  await session.execute(user_update)
394
432
  await session.commit()
395
- return (f"你以 {fish_price} {fishing_coin_name} / 条的价格卖出了 {quantity} 条 {fish_name}, "
396
- f"你获得了 {fish_price * quantity} {fishing_coin_name}")
433
+ return (
434
+ f"你以 {fish_price} {fishing_coin_name} / 条的价格卖出了 {quantity} {fish_name}, "
435
+ f"你获得了 {fish_price * quantity} {fishing_coin_name}"
436
+ )
397
437
  elif fish_name in spec_fishes and spec_fishes[fish_name] > 0:
398
438
  fish_price = config.special_fish_price
399
439
  if spec_fishes[fish_name] < quantity:
@@ -402,31 +442,61 @@ async def sell_fish(user_id: str, fish_name: str, quantity: int = 1) -> str:
402
442
  if spec_fishes[fish_name] == 0:
403
443
  del spec_fishes[fish_name]
404
444
  dump_fishes = json.dumps(spec_fishes)
405
- user_update = update(FishingRecord).where(
406
- FishingRecord.user_id == user_id
407
- ).values(
408
- coin=fishes_record.coin + fish_price * quantity,
409
- special_fishes=dump_fishes
445
+ user_update = (
446
+ update(FishingRecord)
447
+ .where(FishingRecord.user_id == user_id)
448
+ .values(
449
+ coin=fishes_record.coin + fish_price * quantity,
450
+ special_fishes=dump_fishes,
451
+ )
410
452
  )
411
453
  await session.execute(user_update)
412
454
  await session.commit()
413
- return (f"你以 {fish_price} {fishing_coin_name} / 条的价格卖出了 {quantity} 条 {fish_name}, "
414
- f"获得了 {fish_price * quantity} {fishing_coin_name}")
415
- else:
455
+ return (
456
+ f"你以 {fish_price} {fishing_coin_name} / 条的价格卖出了 {quantity} {fish_name}, "
457
+ f"获得了 {fish_price * quantity} {fishing_coin_name}"
458
+ )
459
+ else:
416
460
  return "查无此鱼"
417
461
  else:
418
462
  return "还没钓鱼就想卖鱼?"
419
463
 
420
464
 
421
- async def get_balance(user_id: str) -> str:
422
- """获取余额"""
465
+ async def buy_fish(user_id: str, fish_name: str, quantity: int = 1) -> str:
466
+ if quantity <= 0:
467
+ return "别在渔具店老板面前炫耀自己的鱼 (..-˘ ˘-.#)"
468
+ if fish_name not in can_buy_fishes:
469
+ return "商店不卖这个!"
470
+
471
+ fish = get_fish_by_name(fish_name)
472
+ total_price = int(fish.buy_price * fish.amount * quantity)
473
+
423
474
  session = get_session()
424
475
  async with session.begin():
425
476
  select_user = select(FishingRecord).where(FishingRecord.user_id == user_id)
426
477
  fishes_record = await session.scalar(select_user)
427
- if fishes_record:
428
- return f"🪙你有 {fishes_record.coin} {fishing_coin_name}"
429
- return "🪙你什么也没有 :)"
478
+ if fishes_record := fishes_record:
479
+ loads_fishes = json.loads(fishes_record.fishes)
480
+ user_coin = fishes_record.coin
481
+ if user_coin < total_price:
482
+ coin_less = str(total_price - fishes_record.coin)
483
+ return f"你没有足够的 {fishing_coin_name}, 还需 {coin_less} {fishing_coin_name}"
484
+ user_coin -= total_price
485
+ try:
486
+ loads_fishes[fish_name] += fish.amount * quantity
487
+ except KeyError:
488
+ loads_fishes[fish_name] = fish.amount * quantity
489
+ dump_fishes = json.dumps(loads_fishes)
490
+ user_update = (
491
+ update(FishingRecord)
492
+ .where(FishingRecord.user_id == user_id)
493
+ .values(coin=user_coin, fishes=dump_fishes)
494
+ )
495
+ await session.execute(user_update)
496
+ await session.commit()
497
+ return f"你用 {total_price} {fishing_coin_name} 买入了 {quantity} 份 {fish_name}"
498
+ else:
499
+ return "不想钓鱼的人就别在渔具店逛了~"
430
500
 
431
501
 
432
502
  async def free_fish(user_id: str, fish_name: str) -> str:
@@ -441,16 +511,13 @@ async def free_fish(user_id: str, fish_name: str) -> str:
441
511
  spec_fishes[fish_name] -= 1
442
512
  if spec_fishes[fish_name] == 0:
443
513
  del spec_fishes[fish_name]
444
- new_record = SpecialFishes(
445
- user_id=user_id,
446
- fish=fish_name
447
- )
514
+ new_record = SpecialFishes(user_id=user_id, fish=fish_name)
448
515
  session.add(new_record)
449
516
  dump_fishes = json.dumps(spec_fishes)
450
- user_update = update(FishingRecord).where(
451
- FishingRecord.user_id == user_id
452
- ).values(
453
- special_fishes=dump_fishes
517
+ user_update = (
518
+ update(FishingRecord)
519
+ .where(FishingRecord.user_id == user_id)
520
+ .values(special_fishes=dump_fishes)
454
521
  )
455
522
  await session.execute(user_update)
456
523
  await session.commit()
@@ -458,24 +525,23 @@ async def free_fish(user_id: str, fish_name: str) -> str:
458
525
  else:
459
526
  if fish_name in fish_list:
460
527
  return "普通鱼不能放生哦~"
461
-
462
- if user_coin < config.special_fish_price // 2:
463
- special_fish_coin_less = str(config.special_fish_price // 2 - fishes_record.coin)
528
+
529
+ if user_coin < config.special_fish_free_price:
530
+ special_fish_coin_less = str(
531
+ config.special_fish_free_price - fishes_record.coin
532
+ )
464
533
  return f"你没有足够的 {fishing_coin_name}, 还需 {special_fish_coin_less} {fishing_coin_name}"
465
- user_coin -= config.special_fish_price // 2
466
- new_record = SpecialFishes(
467
- user_id=user_id,
468
- fish=fish_name
469
- )
534
+ user_coin -= config.special_fish_free_price
535
+ new_record = SpecialFishes(user_id=user_id, fish=fish_name)
470
536
  session.add(new_record)
471
- user_update = update(FishingRecord).where(
472
- FishingRecord.user_id == user_id
473
- ).values(
474
- coin=user_coin
537
+ user_update = (
538
+ update(FishingRecord)
539
+ .where(FishingRecord.user_id == user_id)
540
+ .values(coin=user_coin)
475
541
  )
476
542
  await session.execute(user_update)
477
543
  await session.commit()
478
- return f"你花费 {config.special_fish_price // 2} {fishing_coin_name} 放生了 {fish_name}, 未来或许会被有缘人钓到呢"
544
+ return f"你花费 {config.special_fish_free_price} {fishing_coin_name} 放生了 {fish_name}, 未来或许会被有缘人钓到呢"
479
545
  return "你甚至还没钓过鱼"
480
546
 
481
547
 
@@ -491,24 +557,28 @@ async def lottery(user_id: str) -> str:
491
557
  user_coin = fishes_record.coin
492
558
  if user_coin <= 30:
493
559
  new_coin = random.randrange(1, 50)
494
- user_update = update(FishingRecord).where(
495
- FishingRecord.user_id == user_id
496
- ).values(
497
- time=time_now + fishing_limit,
498
- coin=fishes_record.coin + new_coin,
560
+ user_update = (
561
+ update(FishingRecord)
562
+ .where(FishingRecord.user_id == user_id)
563
+ .values(
564
+ time=time_now + fishing_limit,
565
+ coin=fishes_record.coin + new_coin,
566
+ )
499
567
  )
500
568
  await session.execute(user_update)
501
- await session.commit()
569
+ await session.commit()
502
570
  return f"你穷得连河神都看不下去了,给了你 {new_coin} {fishing_coin_name} w(゚Д゚)w"
503
571
  new_coin = abs(user_coin) / 3
504
572
  new_coin = random.randrange(5000, 15000) / 10000 * new_coin
505
573
  new_coin = int(new_coin) if new_coin > 1 else 1
506
574
  new_coin *= random.randrange(-1, 2, 2)
507
- user_update = update(FishingRecord).where(
508
- FishingRecord.user_id == user_id
509
- ).values(
510
- time=time_now + fishing_limit,
511
- coin=fishes_record.coin + new_coin,
575
+ user_update = (
576
+ update(FishingRecord)
577
+ .where(FishingRecord.user_id == user_id)
578
+ .values(
579
+ time=time_now + fishing_limit,
580
+ coin=fishes_record.coin + new_coin,
581
+ )
512
582
  )
513
583
  await session.execute(user_update)
514
584
  await session.commit()
@@ -523,15 +593,17 @@ async def give(user_id: str, fish_name: str, quantity: int = 1) -> str:
523
593
  select_user = select(FishingRecord).where(FishingRecord.user_id == user_id)
524
594
  record = await session.scalar(select_user)
525
595
  if record:
526
- if fish_name == 'coin' or fish_name == fishing_coin_name:
527
- user_update = update(FishingRecord).where(
528
- FishingRecord.user_id == user_id
529
- ).values(
530
- coin=record.coin + quantity,
596
+ if fish_name == "coin" or fish_name == fishing_coin_name:
597
+ user_update = (
598
+ update(FishingRecord)
599
+ .where(FishingRecord.user_id == user_id)
600
+ .values(
601
+ coin=record.coin + quantity,
602
+ )
531
603
  )
532
604
  await session.execute(user_update)
533
605
  await session.commit()
534
- return f"使用滥权之力成功为 {user_id} {"增加" if quantity >= 0 else "减少"} {abs(quantity)} {fishing_coin_name} ヾ(≧▽≦*)o"
606
+ return f"使用滥权之力成功为 {user_id} {"增加" if quantity >= 0 else "减少"} {abs(quantity)} {fishing_coin_name} ヾ(≧▽≦*)o"
535
607
  loads_fishes = json.loads(record.fishes)
536
608
  spec_fishes = json.loads(record.special_fishes)
537
609
  if fish_name in fish_list:
@@ -540,10 +612,10 @@ async def give(user_id: str, fish_name: str, quantity: int = 1) -> str:
540
612
  except KeyError:
541
613
  loads_fishes[fish_name] = quantity
542
614
  dump_fishes = json.dumps(loads_fishes)
543
- user_update = update(FishingRecord).where(
544
- FishingRecord.user_id == user_id
545
- ).values(
546
- fishes=dump_fishes
615
+ user_update = (
616
+ update(FishingRecord)
617
+ .where(FishingRecord.user_id == user_id)
618
+ .values(fishes=dump_fishes)
547
619
  )
548
620
  await session.execute(user_update)
549
621
  await session.commit()
@@ -553,17 +625,79 @@ async def give(user_id: str, fish_name: str, quantity: int = 1) -> str:
553
625
  except KeyError:
554
626
  spec_fishes[fish_name] = quantity
555
627
  dump_fishes = json.dumps(spec_fishes)
556
- user_update = update(FishingRecord).where(
557
- FishingRecord.user_id == user_id
558
- ).values(
559
- special_fishes=dump_fishes
628
+ user_update = (
629
+ update(FishingRecord)
630
+ .where(FishingRecord.user_id == user_id)
631
+ .values(special_fishes=dump_fishes)
560
632
  )
561
633
  await session.execute(user_update)
562
634
  await session.commit()
563
- return f"使用滥权之力成功将 {fish_name} 添加到 {user_id} 的背包之中 ヾ(≧▽≦*)o"
635
+ return (
636
+ f"使用滥权之力成功将 {fish_name} 添加到 {user_id} 的背包之中 ヾ(≧▽≦*)o"
637
+ )
564
638
  return "未查找到用户信息, 无法执行滥权操作 w(゚Д゚)w"
565
639
 
566
640
 
641
+ async def get_stats(user_id: str) -> str:
642
+ session = get_session()
643
+ async with session.begin():
644
+ select_user = select(FishingRecord).where(FishingRecord.user_id == user_id)
645
+ fishing_record = await session.scalar(select_user)
646
+ if fishing_record:
647
+ return f"🐟你钓上了 {fishing_record.frequency} 条鱼"
648
+ return "🐟你还没有钓过鱼,快去钓鱼吧"
649
+
650
+
651
+ async def get_balance(user_id: str) -> str:
652
+ session = get_session()
653
+ async with session.begin():
654
+ select_user = select(FishingRecord).where(FishingRecord.user_id == user_id)
655
+ fishes_record = await session.scalar(select_user)
656
+ if fishes_record:
657
+ return f"🪙你有 {fishes_record.coin} {fishing_coin_name}"
658
+ return "🪙你什么也没有 :)"
659
+
660
+
661
+ async def get_backpack(user_id: str) -> list[str]:
662
+ session = get_session()
663
+ async with session.begin():
664
+ select_user = select(FishingRecord).where(FishingRecord.user_id == user_id)
665
+ fishes_record = await session.scalar(select_user)
666
+ if fishes_record:
667
+ load_fishes = json.loads(fishes_record.fishes)
668
+ sorted_fishes = {
669
+ key: load_fishes[key] for key in fish_list if key in load_fishes
670
+ }
671
+ load_special_fishes = json.loads(fishes_record.special_fishes)
672
+ if load_special_fishes:
673
+ sorted_special_fishes = {
674
+ key: load_special_fishes[key] for key in sorted(load_special_fishes)
675
+ }
676
+ return print_backpack(sorted_fishes, sorted_special_fishes)
677
+ return (
678
+ ["🎒你的背包里空无一物"]
679
+ if sorted_fishes == {}
680
+ else print_backpack(sorted_fishes)
681
+ )
682
+ return ["🎒你的背包里空无一物"]
683
+
684
+
685
+ def print_backpack(backpack: dict, special_backpack=None) -> list[str]:
686
+ result = [
687
+ f"{fish_name}×{str(quantity)}" for fish_name, quantity in backpack.items()
688
+ ]
689
+ if special_backpack:
690
+ special_result = [
691
+ f"{fish_name}×{str(quantity)}"
692
+ for fish_name, quantity in special_backpack.items()
693
+ ]
694
+ return [
695
+ "🎒普通鱼:\n" + "\n".join(result),
696
+ "🎒特殊鱼:\n" + "\n".join(special_result),
697
+ ]
698
+ return ["🎒普通鱼:\n" + "\n".join(result)]
699
+
700
+
567
701
  async def get_achievements(user_id: str) -> str:
568
702
  session = get_session()
569
703
  async with session.begin():
@@ -574,10 +708,13 @@ async def get_achievements(user_id: str) -> str:
574
708
  return "已完成成就:\n" + "\n".join(achievements)
575
709
  return "你甚至还没钓过鱼 (╬▔皿▔)╯"
576
710
 
577
- async def get_board() -> list:
711
+
712
+ async def get_board() -> list[tuple]:
578
713
  session = get_session()
579
714
  async with session.begin():
580
- select_users = select(FishingRecord).order_by(FishingRecord.coin.desc()).limit(10)
715
+ select_users = (
716
+ select(FishingRecord).order_by(FishingRecord.coin.desc()).limit(10)
717
+ )
581
718
  record = await session.scalars(select_users)
582
719
  if record:
583
720
  top_users_list = []
@@ -587,53 +724,20 @@ async def get_board() -> list:
587
724
  return top_users_list
588
725
  return []
589
726
 
590
- async def get_shop() -> str | None:
591
- pass
592
727
 
593
- async def check_tools(user_id: str, tools: list) -> str | None:
594
- # 这是工具吗?
595
- for tool in tools:
596
- props = get_props(tool)
597
- if not props or props == []:
598
- return f"搞啥嘞!{tool}既不是工具也不是鱼饵!"
728
+ def get_shop() -> list[MessageSegment]:
729
+ messages: list[MessageSegment] = []
599
730
 
600
- # 如果有两个工具,是一个工具一个鱼饵吗?
601
- if len(tools) == 2:
602
- if get_type(tool[0]) == get_type(tool[1]):
603
- return "你为啥要用两个类型一样的东西?"
604
-
605
- # 有吗?有吗?
606
- session = get_session()
607
- async with session.begin():
608
- select_user = select(FishingRecord).where(FishingRecord.user_id == user_id)
609
- fishes_record = await session.scalar(select_user)
610
- if fishes_record:
611
- loads_fishes = json.loads(fishes_record.fishes)
612
- for tool in tools:
613
- if tool not in loads_fishes:
614
- return f"你哪来的 {tool}?"
615
-
616
- return None
731
+ messages.append(MessageSegment.text("===== 钓鱼用具店 ====="))
617
732
 
618
- async def remove_tools(user_id: str, tools: list[str]) -> None:
619
- session = get_session()
620
- async with session.begin():
621
- select_user = select(FishingRecord).where(FishingRecord.user_id == user_id)
622
- fishes_record = await session.scalar(select_user)
623
- if fishes_record:
624
- loads_fishes = json.loads(fishes_record.fishes)
625
- for tool in tools:
626
- loads_fishes[tool] -= 1
627
- if loads_fishes[tool] == 0:
628
- del loads_fishes[tool]
629
- dump_fishes = json.dumps(loads_fishes)
630
- user_update = update(FishingRecord).where(
631
- FishingRecord.user_id == user_id
632
- ).values(
633
- fishes=dump_fishes
733
+ for fish in config_fishes:
734
+ if fish.can_buy:
735
+ total_price = int(fish.buy_price * fish.amount)
736
+ messages.append(
737
+ MessageSegment.text(
738
+ f"商品名:{fish.name} \n单份数量:{fish.amount}\n单价:{fish.buy_price} {fishing_coin_name}\n"
739
+ f"单份总价:{total_price} {fishing_coin_name}\n描述:{fish.description}"
740
+ )
634
741
  )
635
- await session.execute(user_update)
636
- await session.commit()
637
- else:
638
- pass
639
- # raise ValueError("?你的 Check 是怎么通过的?")
742
+
743
+ return messages