✨ 更新数据库逻辑
@ -28,7 +28,7 @@ __plugin_meta__ = PluginMetadata(
|
|||||||
收获
|
收获
|
||||||
铲除
|
铲除
|
||||||
我的作物
|
我的作物
|
||||||
出售作物 [作物/种子名称] [数量]
|
出售作物 [作物/种子名称] [数量] (不填写作物
|
||||||
偷菜 at
|
偷菜 at
|
||||||
开垦
|
开垦
|
||||||
购买农场币 [数量] 数量为消耗金币的数量
|
购买农场币 [数量] 数量为消耗金币的数量
|
||||||
|
|||||||
@ -8,80 +8,164 @@
|
|||||||
{
|
{
|
||||||
"4":
|
"4":
|
||||||
{
|
{
|
||||||
"level": 2,
|
"level": 2,
|
||||||
"point": 800,
|
"point": 800,
|
||||||
"item": []
|
"item": []
|
||||||
},
|
},
|
||||||
"5":
|
"5":
|
||||||
{
|
{
|
||||||
"level": 3,
|
"level": 3,
|
||||||
"point": 1300,
|
"point": 1300,
|
||||||
"item": []
|
"item": []
|
||||||
},
|
},
|
||||||
"6":
|
"6":
|
||||||
{
|
{
|
||||||
"level": 5,
|
"level": 5,
|
||||||
"point": 3200,
|
"point": 3200,
|
||||||
"item": []
|
"item": []
|
||||||
},
|
},
|
||||||
"7":
|
"7":
|
||||||
{
|
{
|
||||||
"level": 7,
|
"level": 7,
|
||||||
"point": 5500,
|
"point": 5500,
|
||||||
"item": []
|
"item": []
|
||||||
},
|
},
|
||||||
"8":
|
"8":
|
||||||
{
|
{
|
||||||
"level": 9,
|
"level": 9,
|
||||||
"point": 12000,
|
"point": 12000,
|
||||||
"item": []
|
"item": []
|
||||||
},
|
},
|
||||||
"9":
|
"9":
|
||||||
{
|
{
|
||||||
"level": 15,
|
"level": 11,
|
||||||
"point": 19800,
|
"point": 19800,
|
||||||
"item": []
|
"item": []
|
||||||
},
|
},
|
||||||
"10":
|
"10":
|
||||||
{
|
{
|
||||||
"level":3,
|
"level": 13,
|
||||||
"point": 3000,
|
"point": 30000,
|
||||||
"item": []
|
"item": []
|
||||||
},
|
},
|
||||||
"11":
|
"11":
|
||||||
{
|
{
|
||||||
"level":3,
|
"level": 15,
|
||||||
"point": 3000,
|
"point": 50000,
|
||||||
"item": []
|
"item": []
|
||||||
},
|
},
|
||||||
"12":
|
"12":
|
||||||
{
|
{
|
||||||
"level":3,
|
"level": 17,
|
||||||
"point": 3000,
|
"point": 70000,
|
||||||
"item": []
|
"item": []
|
||||||
},
|
},
|
||||||
"13":
|
"13":
|
||||||
{
|
{
|
||||||
"level":3,
|
"level": 19,
|
||||||
"point": 3000,
|
"point": 90000,
|
||||||
"item": []
|
"item": []
|
||||||
},
|
},
|
||||||
"14":
|
"14":
|
||||||
{
|
{
|
||||||
"level":3,
|
"level": 21,
|
||||||
"point": 3000,
|
"point": 130000,
|
||||||
"item": []
|
"item": []
|
||||||
},
|
},
|
||||||
"15":
|
"15":
|
||||||
{
|
{
|
||||||
"level":3,
|
"level": 23,
|
||||||
"point": 3000,
|
"point": 150000,
|
||||||
"item": []
|
"item": []
|
||||||
},
|
},
|
||||||
"16":
|
"16":
|
||||||
{
|
{
|
||||||
"level":3,
|
"level": 25,
|
||||||
"point": 3000,
|
"point": 180000,
|
||||||
|
"item": []
|
||||||
|
},
|
||||||
|
"17":
|
||||||
|
{
|
||||||
|
"level": 27,
|
||||||
|
"point": 230000,
|
||||||
|
"item": []
|
||||||
|
},
|
||||||
|
"18":
|
||||||
|
{
|
||||||
|
"level": 29,
|
||||||
|
"point": 300000,
|
||||||
|
"item": []
|
||||||
|
},
|
||||||
|
"19":
|
||||||
|
{
|
||||||
|
"level": 31,
|
||||||
|
"point": 500000,
|
||||||
|
"item": []
|
||||||
|
},
|
||||||
|
"20":
|
||||||
|
{
|
||||||
|
"level": 33,
|
||||||
|
"point": 850000,
|
||||||
|
"item": []
|
||||||
|
},
|
||||||
|
"21":
|
||||||
|
{
|
||||||
|
"level": 36,
|
||||||
|
"point": 1100000,
|
||||||
|
"item": []
|
||||||
|
},
|
||||||
|
"22":
|
||||||
|
{
|
||||||
|
"level": 39,
|
||||||
|
"point": 1300000,
|
||||||
|
"item": []
|
||||||
|
},
|
||||||
|
"23":
|
||||||
|
{
|
||||||
|
"level": 42,
|
||||||
|
"point": 1500000,
|
||||||
|
"item": []
|
||||||
|
},
|
||||||
|
"24":
|
||||||
|
{
|
||||||
|
"level": 45,
|
||||||
|
"point": 1700000,
|
||||||
|
"item": []
|
||||||
|
},
|
||||||
|
"25":
|
||||||
|
{
|
||||||
|
"level": 48,
|
||||||
|
"point": 2000000,
|
||||||
|
"item": []
|
||||||
|
},
|
||||||
|
"26":
|
||||||
|
{
|
||||||
|
"level": 51,
|
||||||
|
"point": 2200000,
|
||||||
|
"item": []
|
||||||
|
},
|
||||||
|
"27":
|
||||||
|
{
|
||||||
|
"level": 54,
|
||||||
|
"point": 2800000,
|
||||||
|
"item": []
|
||||||
|
},
|
||||||
|
"28":
|
||||||
|
{
|
||||||
|
"level": 57,
|
||||||
|
"point": 3500000,
|
||||||
|
"item": []
|
||||||
|
},
|
||||||
|
"29":
|
||||||
|
{
|
||||||
|
"level": 60,
|
||||||
|
"point": 4300000,
|
||||||
|
"item": []
|
||||||
|
},
|
||||||
|
"30":
|
||||||
|
{
|
||||||
|
"level": 70,
|
||||||
|
"point": 5200000,
|
||||||
"item": []
|
"item": []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,10 +3,11 @@
|
|||||||
"zhuShi":
|
"zhuShi":
|
||||||
[
|
[
|
||||||
"level: 解锁等级",
|
"level: 解锁等级",
|
||||||
|
"buy: 购买价格",
|
||||||
"limit: 限制等级 0:普通土地 1:红土地 2:黄土地 3:黑土地",
|
"limit: 限制等级 0:普通土地 1:红土地 2:黄土地 3:黑土地",
|
||||||
"experience: 收获经验",
|
"experience: 收获经验",
|
||||||
"harvest: 收获数量",
|
"harvest: 收获数量",
|
||||||
"price: 单价",
|
"price: 果实售价",
|
||||||
"time: 成熟时间 小时",
|
"time: 成熟时间 小时",
|
||||||
"crop: 作物可以收几次",
|
"crop: 作物可以收几次",
|
||||||
"again: 再次成熟时间 单位:小时",
|
"again: 再次成熟时间 单位:小时",
|
||||||
@ -19,6 +20,7 @@
|
|||||||
"胡萝卜":
|
"胡萝卜":
|
||||||
{
|
{
|
||||||
"level": 0,
|
"level": 0,
|
||||||
|
"buy": 163,
|
||||||
"limit": 0,
|
"limit": 0,
|
||||||
"experience": 18,
|
"experience": 18,
|
||||||
"harvest": 17,
|
"harvest": 17,
|
||||||
@ -33,6 +35,7 @@
|
|||||||
"白萝卜":
|
"白萝卜":
|
||||||
{
|
{
|
||||||
"level": 0,
|
"level": 0,
|
||||||
|
"buy": 125,
|
||||||
"limit": 0,
|
"limit": 0,
|
||||||
"experience": 15,
|
"experience": 15,
|
||||||
"harvest": 16,
|
"harvest": 16,
|
||||||
@ -47,6 +50,7 @@
|
|||||||
"牧草":
|
"牧草":
|
||||||
{
|
{
|
||||||
"level": 0,
|
"level": 0,
|
||||||
|
"buy": 80,
|
||||||
"limit": 0,
|
"limit": 0,
|
||||||
"experience": 10,
|
"experience": 10,
|
||||||
"harvest": 25,
|
"harvest": 25,
|
||||||
@ -61,6 +65,7 @@
|
|||||||
"大白菜":
|
"大白菜":
|
||||||
{
|
{
|
||||||
"level": 1,
|
"level": 1,
|
||||||
|
"buy": 168,
|
||||||
"limit": 0,
|
"limit": 0,
|
||||||
"experience": 19,
|
"experience": 19,
|
||||||
"harvest": 17,
|
"harvest": 17,
|
||||||
@ -75,6 +80,7 @@
|
|||||||
"大蒜":
|
"大蒜":
|
||||||
{
|
{
|
||||||
"level": 1,
|
"level": 1,
|
||||||
|
"buy": 169,
|
||||||
"limit": 0,
|
"limit": 0,
|
||||||
"experience": 19,
|
"experience": 19,
|
||||||
"harvest": 17,
|
"harvest": 17,
|
||||||
@ -89,6 +95,7 @@
|
|||||||
"水稻":
|
"水稻":
|
||||||
{
|
{
|
||||||
"level": 2,
|
"level": 2,
|
||||||
|
"buy": 168,
|
||||||
"limit": 0,
|
"limit": 0,
|
||||||
"experience": 19,
|
"experience": 19,
|
||||||
"harvest": 18,
|
"harvest": 18,
|
||||||
@ -96,13 +103,14 @@
|
|||||||
"time": 14,
|
"time": 14,
|
||||||
"crop": 1,
|
"crop": 1,
|
||||||
"again": 0,
|
"again": 0,
|
||||||
"phase": 6,
|
"phase": 5,
|
||||||
"general": true,
|
"general": false,
|
||||||
"sell": false
|
"sell": false
|
||||||
},
|
},
|
||||||
"小麦":
|
"小麦":
|
||||||
{
|
{
|
||||||
"level": 2,
|
"level": 2,
|
||||||
|
"buy": 168,
|
||||||
"limit": 0,
|
"limit": 0,
|
||||||
"experience": 19,
|
"experience": 19,
|
||||||
"harvest": 18,
|
"harvest": 18,
|
||||||
@ -117,6 +125,7 @@
|
|||||||
"玉米":
|
"玉米":
|
||||||
{
|
{
|
||||||
"level": 3,
|
"level": 3,
|
||||||
|
"buy": 175,
|
||||||
"limit": 0,
|
"limit": 0,
|
||||||
"experience": 19,
|
"experience": 19,
|
||||||
"harvest": 17,
|
"harvest": 17,
|
||||||
@ -131,6 +140,7 @@
|
|||||||
"油菜":
|
"油菜":
|
||||||
{
|
{
|
||||||
"level": 4,
|
"level": 4,
|
||||||
|
"buy": 194,
|
||||||
"limit": 0,
|
"limit": 0,
|
||||||
"experience": 29,
|
"experience": 29,
|
||||||
"harvest": 23,
|
"harvest": 23,
|
||||||
@ -145,6 +155,7 @@
|
|||||||
"生菜":
|
"生菜":
|
||||||
{
|
{
|
||||||
"level": 4,
|
"level": 4,
|
||||||
|
"buy": 195,
|
||||||
"limit": 0,
|
"limit": 0,
|
||||||
"experience": 25,
|
"experience": 25,
|
||||||
"harvest": 21,
|
"harvest": 21,
|
||||||
@ -155,6 +166,96 @@
|
|||||||
"phase": 6,
|
"phase": 6,
|
||||||
"general": true,
|
"general": true,
|
||||||
"sell": false
|
"sell": false
|
||||||
|
},
|
||||||
|
"小白菜":
|
||||||
|
{
|
||||||
|
"level": 4,
|
||||||
|
"buy": 195,
|
||||||
|
"limit": 0,
|
||||||
|
"experience": 15,
|
||||||
|
"harvest": 18,
|
||||||
|
"price": 21,
|
||||||
|
"time": 11,
|
||||||
|
"crop": 1,
|
||||||
|
"again": 0,
|
||||||
|
"phase": 5,
|
||||||
|
"general": true,
|
||||||
|
"sell": false
|
||||||
|
},
|
||||||
|
"红枣":
|
||||||
|
{
|
||||||
|
"level": 5,
|
||||||
|
"buy": 237,
|
||||||
|
"limit": 0,
|
||||||
|
"experience": 21,
|
||||||
|
"harvest": 20,
|
||||||
|
"price": 25,
|
||||||
|
"time": 16,
|
||||||
|
"crop": 1,
|
||||||
|
"again": 0,
|
||||||
|
"phase": 6,
|
||||||
|
"general": true,
|
||||||
|
"sell": false
|
||||||
|
},
|
||||||
|
"茄子":
|
||||||
|
{
|
||||||
|
"level": 5,
|
||||||
|
"buy": 237,
|
||||||
|
"limit": 0,
|
||||||
|
"experience": 21,
|
||||||
|
"harvest": 20,
|
||||||
|
"price": 25,
|
||||||
|
"time": 16,
|
||||||
|
"crop": 1,
|
||||||
|
"again": 0,
|
||||||
|
"phase": 6,
|
||||||
|
"general": true,
|
||||||
|
"sell": false
|
||||||
|
},
|
||||||
|
"番茄":
|
||||||
|
{
|
||||||
|
"level": 6,
|
||||||
|
"buy": 99999,
|
||||||
|
"limit": 0,
|
||||||
|
"experience": 22,
|
||||||
|
"harvest": 21,
|
||||||
|
"price": 7000,
|
||||||
|
"time": 17,
|
||||||
|
"crop": 1,
|
||||||
|
"again": 0,
|
||||||
|
"phase": 6,
|
||||||
|
"general": true,
|
||||||
|
"sell": false
|
||||||
|
},
|
||||||
|
"红玫瑰":
|
||||||
|
{
|
||||||
|
"level": 7,
|
||||||
|
"buy": 251,
|
||||||
|
"limit": 0,
|
||||||
|
"experience": 23,
|
||||||
|
"harvest": 22,
|
||||||
|
"price": 27,
|
||||||
|
"time": 18,
|
||||||
|
"crop": 1,
|
||||||
|
"again": 0,
|
||||||
|
"phase": 6,
|
||||||
|
"general": true,
|
||||||
|
"sell": false
|
||||||
|
},
|
||||||
|
"豌豆":
|
||||||
|
{
|
||||||
|
"level": 7,
|
||||||
|
"buy": 266,
|
||||||
|
"limit": 0,
|
||||||
|
"experience": 23,
|
||||||
|
"harvest": 22,
|
||||||
|
"price": 27,
|
||||||
|
"time": 18,
|
||||||
|
"crop": 1,
|
||||||
|
"again": 0,
|
||||||
|
"phase": 6,
|
||||||
|
"general": true,
|
||||||
|
"sell": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
122
database.py
@ -28,10 +28,7 @@ class CSqlManager:
|
|||||||
bIsExist = os.path.exists(g_sDBFilePath)
|
bIsExist = os.path.exists(g_sDBFilePath)
|
||||||
|
|
||||||
cls.m_pDB = await aiosqlite.connect(g_sDBFilePath)
|
cls.m_pDB = await aiosqlite.connect(g_sDBFilePath)
|
||||||
|
cls.m_pDB.row_factory = aiosqlite.Row
|
||||||
#if bIsExist == False:
|
|
||||||
#TODO 缺少判断创建失败事件
|
|
||||||
#await cls.createDB()
|
|
||||||
|
|
||||||
await cls.checkDB()
|
await cls.checkDB()
|
||||||
|
|
||||||
@ -50,11 +47,11 @@ class CSqlManager:
|
|||||||
await cls.m_pDB.execute("COMMIT;")
|
await cls.m_pDB.execute("COMMIT;")
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def getTableInfo(cls, table_name: str) -> list:
|
async def getTableInfo(cls, tableName: str) -> list:
|
||||||
if not re.match(r'^[A-Za-z_][A-Za-z0-9_]*$', table_name):
|
if not re.match(r'^[A-Za-z_][A-Za-z0-9_]*$', tableName):
|
||||||
raise ValueError(f"Illegal table name: {table_name}")
|
raise ValueError(f"Illegal table name: {tableName}")
|
||||||
try:
|
try:
|
||||||
cursor = await cls.m_pDB.execute(f'PRAGMA table_info("{table_name}")')
|
cursor = await cls.m_pDB.execute(f'PRAGMA table_info("{tableName}")')
|
||||||
rows = await cursor.fetchall()
|
rows = await cursor.fetchall()
|
||||||
return [{"name": row[1], "type": row[2]} for row in rows]
|
return [{"name": row[1], "type": row[2]} for row in rows]
|
||||||
except aiosqlite.Error:
|
except aiosqlite.Error:
|
||||||
@ -62,7 +59,7 @@ class CSqlManager:
|
|||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def ensureTableSchema(cls, table_name: str, columns: dict) -> bool:
|
async def ensureTableSchema(cls, tableName: str, columns: dict) -> bool:
|
||||||
"""由AI生成
|
"""由AI生成
|
||||||
创建表或为已存在表添加缺失字段。
|
创建表或为已存在表添加缺失字段。
|
||||||
返回 True 表示有变更(创建或新增列),False 则无操作
|
返回 True 表示有变更(创建或新增列),False 则无操作
|
||||||
@ -75,34 +72,44 @@ class CSqlManager:
|
|||||||
_type_: _description_
|
_type_: _description_
|
||||||
"""
|
"""
|
||||||
|
|
||||||
info = await cls.getTableInfo(table_name)
|
info = await cls.getTableInfo(tableName)
|
||||||
existing = {col['name']: col['type'].upper() for col in info}
|
existing = {col['name']: col['type'].upper() for col in info}
|
||||||
desired = {k: v.upper() for k, v in columns.items()}
|
desired = {k: v.upper() for k, v in columns.items() if k != "PRIMARY KEY"}
|
||||||
|
primaryKey = columns.get("PRIMARY KEY", "")
|
||||||
|
|
||||||
if not existing:
|
if not existing:
|
||||||
cols_def = ", ".join(f'"{k}" {v}' for k, v in columns.items())
|
colsDef = ", ".join(f'"{k}" {v}' for k, v in desired.items())
|
||||||
await cls.m_pDB.execute(f'CREATE TABLE "{table_name}" ({cols_def});')
|
if primaryKey:
|
||||||
|
colsDef += f", PRIMARY KEY {primaryKey}"
|
||||||
|
await cls.m_pDB.execute(f'CREATE TABLE "{tableName}" ({colsDef});')
|
||||||
return True
|
return True
|
||||||
to_add = [k for k in desired if k not in existing]
|
|
||||||
to_remove = [k for k in existing if k not in desired]
|
toAdd = [k for k in desired if k not in existing]
|
||||||
type_mismatch = [k for k in desired if k in existing and existing[k] != desired[k]]
|
toRemove = [k for k in existing if k not in desired]
|
||||||
if to_add and not to_remove and not type_mismatch:
|
typeMismatch = [k for k in desired if k in existing and existing[k] != desired[k]]
|
||||||
for col in to_add:
|
|
||||||
|
if toAdd and not toRemove and not typeMismatch:
|
||||||
|
for col in toAdd:
|
||||||
await cls.m_pDB.execute(
|
await cls.m_pDB.execute(
|
||||||
f'ALTER TABLE "{table_name}" ADD COLUMN "{col}" {columns[col]}'
|
f'ALTER TABLE "{tableName}" ADD COLUMN "{col}" {columns[col]}'
|
||||||
)
|
)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
async with cls._transaction():
|
async with cls._transaction():
|
||||||
tmp_table = f"{table_name}_new"
|
tmpTable = f"{tableName}_new"
|
||||||
cols_def = ", ".join(f'"{k}" {v}' for k, v in columns.items())
|
colsDef = ", ".join(f'"{k}" {v}' for k, v in desired.items())
|
||||||
await cls.m_pDB.execute(f'CREATE TABLE "{tmp_table}" ({cols_def});')
|
if primaryKey:
|
||||||
common_cols = [k for k in desired if k in existing]
|
colsDef += f", PRIMARY KEY {primaryKey}"
|
||||||
if common_cols:
|
await cls.m_pDB.execute(f'CREATE TABLE "{tmpTable}" ({colsDef});')
|
||||||
cols_str = ", ".join(f'"{c}"' for c in common_cols)
|
|
||||||
|
commonCols = [k for k in desired if k in existing]
|
||||||
|
if commonCols:
|
||||||
|
colsStr = ", ".join(f'"{c}"' for c in commonCols)
|
||||||
await cls.m_pDB.execute(
|
await cls.m_pDB.execute(
|
||||||
f'INSERT INTO "{tmp_table}" ({cols_str}) SELECT {cols_str} FROM "{table_name}";'
|
f'INSERT INTO "{tmpTable}" ({colsStr}) SELECT {colsStr} FROM "{tableName}";'
|
||||||
)
|
)
|
||||||
await cls.m_pDB.execute(f'DROP TABLE "{table_name}";')
|
await cls.m_pDB.execute(f'DROP TABLE "{tableName}";')
|
||||||
await cls.m_pDB.execute(f'ALTER TABLE "{tmp_table}" RENAME TO "{table_name}";')
|
await cls.m_pDB.execute(f'ALTER TABLE "{tmpTable}" RENAME TO "{tableName}";')
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -155,17 +162,16 @@ class CSqlManager:
|
|||||||
Returns:
|
Returns:
|
||||||
bool: 是否执行成功
|
bool: 是否执行成功
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if len(command) <= 0:
|
if len(command) <= 0:
|
||||||
logger.warning("数据库语句长度不能!")
|
logger.warning("数据库语句长度为空!")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
try:
|
try:
|
||||||
await cls.m_pDB.execute(command)
|
async with cls._transaction():
|
||||||
await cls.m_pDB.commit()
|
await cls.m_pDB.execute(command)
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning("数据库语句执行出错:" + command)
|
logger.warning("数据库语句执行出错:" + command)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -483,8 +489,6 @@ class CSqlManager:
|
|||||||
"DELETE FROM userSeed WHERE uid = ? AND seed = ?",
|
"DELETE FROM userSeed WHERE uid = ? AND seed = ?",
|
||||||
(uid, seed)
|
(uid, seed)
|
||||||
)
|
)
|
||||||
|
|
||||||
await cls.m_pDB.commit()
|
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(f"真寻农场addUserSeedByUid 失败: {e}")
|
logger.warning(f"真寻农场addUserSeedByUid 失败: {e}")
|
||||||
@ -543,17 +547,18 @@ class CSqlManager:
|
|||||||
Returns:
|
Returns:
|
||||||
bool: 是否成功
|
bool: 是否成功
|
||||||
"""
|
"""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
if count <= 0:
|
||||||
|
return await cls.deleteUserSeedByName(uid, seed)
|
||||||
|
|
||||||
async with cls._transaction():
|
async with cls._transaction():
|
||||||
await cls.m_pDB.execute(
|
await cls.m_pDB.execute(
|
||||||
"UPDATE userSeed SET count = ? WHERE uid = ? AND seed = ?",
|
"UPDATE userSeed SET count = ? WHERE uid = ? AND seed = ?",
|
||||||
(count, uid, seed)
|
(count, uid, seed)
|
||||||
)
|
)
|
||||||
await cls.m_pDB.commit()
|
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(f"真寻农场updateUserSeedByName 更新失败: {e}")
|
logger.warning(f"真寻农场updateUserSeedByName失败:{e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -573,7 +578,6 @@ class CSqlManager:
|
|||||||
"DELETE FROM userSeed WHERE uid = ? AND seed = ?",
|
"DELETE FROM userSeed WHERE uid = ? AND seed = ?",
|
||||||
(uid, seed)
|
(uid, seed)
|
||||||
)
|
)
|
||||||
await cls.m_pDB.commit()
|
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(f"真寻农场deleteUserSeedByName 删除失败: {e}")
|
logger.warning(f"真寻农场deleteUserSeedByName 删除失败: {e}")
|
||||||
@ -613,12 +617,28 @@ class CSqlManager:
|
|||||||
"INSERT INTO userPlant (uid, plant, count) VALUES (?, ?, ?)",
|
"INSERT INTO userPlant (uid, plant, count) VALUES (?, ?, ?)",
|
||||||
(uid, plant, count)
|
(uid, plant, count)
|
||||||
)
|
)
|
||||||
await cls.m_pDB.commit()
|
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(f"真寻农场addUserPlantByUid 失败: {e}")
|
logger.warning(f"真寻农场addUserPlantByUid 失败: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def getUserPlantByUid(cls, uid: str) -> Dict[str, int]:
|
||||||
|
"""根据用户uid获取全部作物信息
|
||||||
|
|
||||||
|
Args:
|
||||||
|
uid (str): 用户uid
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Dict[str, int]: 作物名称和数量
|
||||||
|
"""
|
||||||
|
cursor = await cls.m_pDB.execute(
|
||||||
|
"SELECT plant, count FROM userPlant WHERE uid=?",
|
||||||
|
(uid,)
|
||||||
|
)
|
||||||
|
rows = await cursor.fetchall()
|
||||||
|
return {row["plant"]: row["count"] for row in rows}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def getUserPlantByName(cls, uid: str, plant: str) -> Optional[int]:
|
async def getUserPlantByName(cls, uid: str, plant: str) -> Optional[int]:
|
||||||
"""根据作物名称获取用户的作物数量
|
"""根据作物名称获取用户的作物数量
|
||||||
@ -642,7 +662,7 @@ class CSqlManager:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def updateUserPlantByUid(cls, uid: str, plant: str, count: int) -> bool:
|
async def updateUserPlantByName(cls, uid: str, plant: str, count: int) -> bool:
|
||||||
"""更新 userPlant 表中某个作物的数量
|
"""更新 userPlant 表中某个作物的数量
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -654,28 +674,21 @@ class CSqlManager:
|
|||||||
bool: 是否更新成功
|
bool: 是否更新成功
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
|
if count <= 0:
|
||||||
|
return await cls.deleteUserPlantByName(uid, plant)
|
||||||
|
|
||||||
async with cls._transaction():
|
async with cls._transaction():
|
||||||
#更新作物数量
|
|
||||||
await cls.m_pDB.execute(
|
await cls.m_pDB.execute(
|
||||||
"UPDATE userPlant SET count = ? WHERE uid = ? AND plant = ?",
|
"UPDATE userPlant SET count = ? WHERE uid = ? AND plant = ?",
|
||||||
(count, uid, plant)
|
(count, uid, plant)
|
||||||
)
|
)
|
||||||
|
|
||||||
#如果作物数量为 0,删除记录
|
|
||||||
if count <= 0:
|
|
||||||
await cls.m_pDB.execute(
|
|
||||||
"DELETE FROM userPlant WHERE uid = ? AND plant = ?",
|
|
||||||
(uid, plant)
|
|
||||||
)
|
|
||||||
|
|
||||||
await cls.m_pDB.commit()
|
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(f"真寻农场updateUserPlantByUid 更新失败: {e}")
|
logger.warning(f"真寻农场updateUserPlantByName失败:{e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def deleteUserPlantByUid(cls, uid: str, plant: str) -> bool:
|
async def deleteUserPlantByName(cls, uid: str, plant: str) -> bool:
|
||||||
"""从 userPlant 表中删除某个作物记录
|
"""从 userPlant 表中删除某个作物记录
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -691,10 +704,9 @@ class CSqlManager:
|
|||||||
"DELETE FROM userPlant WHERE uid = ? AND plant = ?",
|
"DELETE FROM userPlant WHERE uid = ? AND plant = ?",
|
||||||
(uid, plant)
|
(uid, plant)
|
||||||
)
|
)
|
||||||
await cls.m_pDB.commit()
|
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(f"真寻农场deleteUserPlantByUid 删除失败: {e}")
|
logger.warning(f"真寻农场deleteUserPlantByName 失败: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
g_pSqlManager = CSqlManager()
|
g_pSqlManager = CSqlManager()
|
||||||
|
|||||||
64
farm/farm.py
@ -213,9 +213,12 @@ class CFarmManager:
|
|||||||
|
|
||||||
currentStage = int(elapsedHour / (plantInfo['time'] / (plantInfo['phase'] - 1)))
|
currentStage = int(elapsedHour / (plantInfo['time'] / (plantInfo['phase'] - 1)))
|
||||||
|
|
||||||
#TODO 缺少判断部分种子是否是通用0阶段图片
|
|
||||||
if currentStage <= 0:
|
if currentStage <= 0:
|
||||||
plant = BuildImage(background = g_sResourcePath / f"plant/basic/0.png")
|
if plantInfo['general'] == False:
|
||||||
|
plant = BuildImage(background = g_sResourcePath / f"plant/{soilInfo[0]}/0.png")
|
||||||
|
else:
|
||||||
|
plant = BuildImage(background = g_sResourcePath / f"plant/basic/0.png")
|
||||||
|
|
||||||
await plant.resize(0, 35, 58)
|
await plant.resize(0, 35, 58)
|
||||||
else:
|
else:
|
||||||
plant = BuildImage(background = g_sResourcePath / f"plant/{soilInfo[0]}/{currentStage}.png")
|
plant = BuildImage(background = g_sResourcePath / f"plant/{soilInfo[0]}/{currentStage}.png")
|
||||||
@ -395,7 +398,7 @@ class CFarmManager:
|
|||||||
harvestRecords.append(f"收获作物:{plantId},数量为:{number},经验为:{plantInfo['experience']}")
|
harvestRecords.append(f"收获作物:{plantId},数量为:{number},经验为:{plantInfo['experience']}")
|
||||||
|
|
||||||
#更新数据库操作
|
#更新数据库操作
|
||||||
await g_pSqlManager.addUserPlantByPlant(uid, plantId, number)
|
await g_pSqlManager.addUserPlantByUid(uid, plantId, number)
|
||||||
await g_pSqlManager.updateUserSoilStatusByPlantName(uid, soil_name, "", 4)
|
await g_pSqlManager.updateUserSoilStatusByPlantName(uid, soil_name, "", 4)
|
||||||
|
|
||||||
if experience > 0:
|
if experience > 0:
|
||||||
@ -455,7 +458,6 @@ class CFarmManager:
|
|||||||
Returns:
|
Returns:
|
||||||
bytes: 返回图片
|
bytes: 返回图片
|
||||||
"""
|
"""
|
||||||
|
|
||||||
data_list = []
|
data_list = []
|
||||||
column_name = [
|
column_name = [
|
||||||
"-",
|
"-",
|
||||||
@ -468,48 +470,40 @@ class CFarmManager:
|
|||||||
|
|
||||||
plant = await g_pSqlManager.getUserPlantByUid(uid)
|
plant = await g_pSqlManager.getUserPlantByUid(uid)
|
||||||
|
|
||||||
if plant == None:
|
if plant is None:
|
||||||
result = await ImageTemplate.table_page(
|
result = await ImageTemplate.table_page(
|
||||||
"作物仓库",
|
"作物仓库",
|
||||||
"播种示例:@小真寻 出售作物 大白菜 [数量]",
|
"播种示例:@小真寻 出售作物 大白菜 [数量]",
|
||||||
column_name,
|
column_name,
|
||||||
data_list,
|
data_list,
|
||||||
)
|
)
|
||||||
|
|
||||||
return result.pic2bytes()
|
return result.pic2bytes()
|
||||||
|
|
||||||
sell = ""
|
sell = ""
|
||||||
for item in plant.split(','):
|
for name, count in plant.items(): # 使用 .items() 来遍历字典
|
||||||
if '|' in item:
|
plantInfo = g_pJsonManager.m_pPlant['plant'][name]
|
||||||
plantName, count = item.split('|', 1) #分割一次,避免多竖线问题
|
icon = ""
|
||||||
try:
|
icon_path = g_sResourcePath / f"plant/{name}/icon.png"
|
||||||
plantInfo = g_pJsonManager.m_pPlant['plant'][plantName]
|
if icon_path.exists():
|
||||||
|
icon = (icon_path, 33, 33)
|
||||||
|
|
||||||
icon = ""
|
if plantInfo['again'] == True:
|
||||||
icon_path = g_sResourcePath / f"plant/{plantName}/icon.png"
|
sell = "可以"
|
||||||
if icon_path.exists():
|
else:
|
||||||
icon = (icon_path, 33, 33)
|
sell = "不可以"
|
||||||
|
|
||||||
if plantInfo['again'] == True:
|
number = int(count) * plantInfo['price']
|
||||||
sell = "可以"
|
|
||||||
else:
|
|
||||||
sell = "不可以"
|
|
||||||
|
|
||||||
number = int(count) * plantInfo['price']
|
data_list.append(
|
||||||
|
[
|
||||||
data_list.append(
|
icon,
|
||||||
[
|
name,
|
||||||
icon,
|
count,
|
||||||
plantName,
|
plantInfo['price'],
|
||||||
count,
|
number,
|
||||||
plantInfo['price'],
|
sell
|
||||||
number,
|
]
|
||||||
sell
|
)
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
continue
|
|
||||||
|
|
||||||
result = await ImageTemplate.table_page(
|
result = await ImageTemplate.table_page(
|
||||||
"作物仓库",
|
"作物仓库",
|
||||||
@ -611,7 +605,7 @@ class CFarmManager:
|
|||||||
logger.info(f"{randomNumber}")
|
logger.info(f"{randomNumber}")
|
||||||
|
|
||||||
if randomNumber > 0:
|
if randomNumber > 0:
|
||||||
await g_pSqlManager.addUserPlantByPlant(uid, plantId, randomNumber)
|
await g_pSqlManager.addUserPlantByUid(uid, plantId, randomNumber)
|
||||||
|
|
||||||
harvestRecords.append(f"成功偷到作物:{plantId},数量为:{randomNumber}")
|
harvestRecords.append(f"成功偷到作物:{plantId},数量为:{randomNumber}")
|
||||||
stealingStatus.append(f"{uid}-{randomNumber}")
|
stealingStatus.append(f"{uid}-{randomNumber}")
|
||||||
|
|||||||
99
farm/shop.py
@ -1,4 +1,5 @@
|
|||||||
import math
|
import math
|
||||||
|
from re import I
|
||||||
|
|
||||||
from zhenxun.services.log import logger
|
from zhenxun.services.log import logger
|
||||||
from zhenxun.utils._build_image import BuildImage
|
from zhenxun.utils._build_image import BuildImage
|
||||||
@ -22,8 +23,9 @@ class CShopManager:
|
|||||||
column_name = [
|
column_name = [
|
||||||
"-",
|
"-",
|
||||||
"种子名称",
|
"种子名称",
|
||||||
|
"种子单价"
|
||||||
"解锁等级",
|
"解锁等级",
|
||||||
"种子单价",
|
"果实单价",
|
||||||
"收获经验",
|
"收获经验",
|
||||||
"收获数量",
|
"收获数量",
|
||||||
"成熟时间(小时)",
|
"成熟时间(小时)",
|
||||||
@ -53,6 +55,7 @@ class CShopManager:
|
|||||||
[
|
[
|
||||||
icon,
|
icon,
|
||||||
key,
|
key,
|
||||||
|
plant['buy'],
|
||||||
plant['level'],
|
plant['level'],
|
||||||
plant['price'],
|
plant['price'],
|
||||||
plant['experience'],
|
plant['experience'],
|
||||||
@ -105,7 +108,7 @@ class CShopManager:
|
|||||||
return "你的等级不够哦,努努力吧"
|
return "你的等级不够哦,努努力吧"
|
||||||
|
|
||||||
point = await g_pSqlManager.getUserPointByUid(uid)
|
point = await g_pSqlManager.getUserPointByUid(uid)
|
||||||
total = int(plantInfo['price']) * num
|
total = int(plantInfo['buy']) * num
|
||||||
|
|
||||||
logger.debug(f"用户:{uid}购买{name},数量为{num}。用户农场币为{point},购买需要{total}")
|
logger.debug(f"用户:{uid}购买{name},数量为{num}。用户农场币为{point},购买需要{total}")
|
||||||
|
|
||||||
@ -114,7 +117,7 @@ class CShopManager:
|
|||||||
else:
|
else:
|
||||||
await g_pSqlManager.updateUserPointByUid(uid, point - total)
|
await g_pSqlManager.updateUserPointByUid(uid, point - total)
|
||||||
|
|
||||||
if await g_pSqlManager.addUserSeedByPlant(uid, name, num) == False:
|
if await g_pSqlManager.addUserSeedByUid(uid, name, num) == False:
|
||||||
return "购买失败,执行数据库错误!"
|
return "购买失败,执行数据库错误!"
|
||||||
|
|
||||||
return f"成功购买{name},花费{total}农场币, 剩余{point - total}农场币"
|
return f"成功购买{name},花费{total}农场币, 剩余{point - total}农场币"
|
||||||
@ -129,81 +132,39 @@ class CShopManager:
|
|||||||
Returns:
|
Returns:
|
||||||
str:
|
str:
|
||||||
"""
|
"""
|
||||||
|
plantDict = await g_pSqlManager.getUserPlantByUid(uid)
|
||||||
plant = await g_pSqlManager.getUserPlantByUid(uid)
|
if not plantDict:
|
||||||
|
|
||||||
if plant == None:
|
|
||||||
return "你仓库没有可以出售的作物"
|
return "你仓库没有可以出售的作物"
|
||||||
|
|
||||||
point = 0
|
totalPoint = 0
|
||||||
totalSold = 0
|
|
||||||
remainingItems = []
|
|
||||||
|
|
||||||
isAll = False
|
if not name:
|
||||||
if num == -1:
|
for plantName, count in plantDict.items():
|
||||||
isAll = True
|
plantInfo = g_pJsonManager.m_pPlant['plant'][plantName]
|
||||||
|
totalPoint += plantInfo['price'] * count
|
||||||
items = plant.split(',')
|
await g_pSqlManager.deleteUserPlantByName(uid, plantName)
|
||||||
if len(name) <= 0:
|
|
||||||
#出售全部
|
|
||||||
for item in items:
|
|
||||||
if '|' in item:
|
|
||||||
plant_name, count_str = item.split('|', 1)
|
|
||||||
try:
|
|
||||||
count = int(count_str)
|
|
||||||
plant_info = g_pJsonManager.m_pPlant['plant'][plant_name]
|
|
||||||
point += plant_info['price'] * count
|
|
||||||
except Exception:
|
|
||||||
continue
|
|
||||||
|
|
||||||
await g_pSqlManager.updateUserPlantByUid(uid, "") # 清空仓库
|
|
||||||
else:
|
else:
|
||||||
for item in items:
|
currentCount = plantDict.get(name)
|
||||||
if '|' in item:
|
if currentCount is None:
|
||||||
plantName, countStr = item.split('|', 1)
|
return f"出售作物{name}出错:你没有这种作物"
|
||||||
try:
|
|
||||||
count = int(countStr)
|
|
||||||
if plantName == name:
|
|
||||||
|
|
||||||
if isAll:
|
if num == -1:
|
||||||
sellAmount = count
|
sellCount = currentCount
|
||||||
else:
|
else:
|
||||||
sellAmount = min(num, count)
|
if num > currentCount:
|
||||||
|
return f"出售作物{name}出错:数量不足"
|
||||||
|
sellCount = num
|
||||||
|
|
||||||
totalSold += sellAmount
|
|
||||||
remaining = count - sellAmount
|
|
||||||
|
|
||||||
if remaining > 0:
|
|
||||||
remainingItems.append(f"{plantName}|{remaining}")
|
|
||||||
|
|
||||||
if isAll == False:
|
|
||||||
num -= sellAmount
|
|
||||||
|
|
||||||
break
|
|
||||||
except (ValueError, TypeError):
|
|
||||||
continue
|
|
||||||
|
|
||||||
if num > 0 and isAll == False:
|
|
||||||
return f"出售作物{name}出错:数量不足"
|
|
||||||
|
|
||||||
#计算收益
|
|
||||||
try:
|
|
||||||
plantInfo = g_pJsonManager.m_pPlant['plant'][name]
|
plantInfo = g_pJsonManager.m_pPlant['plant'][name]
|
||||||
totalPoint = plantInfo['price'] * totalSold
|
totalPoint = plantInfo['price'] * sellCount
|
||||||
except KeyError:
|
await g_pSqlManager.addUserPlantByUid(uid, name, -sellCount)
|
||||||
return f"出售作物{name}出错:作物不存在"
|
|
||||||
|
|
||||||
#更新剩余作物
|
point = await g_pSqlManager.getUserPointByUid(uid)
|
||||||
remainingPlant = ','.join(remainingItems) if remainingItems else ""
|
await g_pSqlManager.updateUserPointByUid(uid, point + totalPoint)
|
||||||
await g_pSqlManager.updateUserPlantByUid(uid, remainingPlant)
|
|
||||||
|
|
||||||
#更新农场币
|
if not name:
|
||||||
p = await g_pSqlManager.getUserPointByUid(uid)
|
return f"成功出售所有作物,获得农场币:{totalPoint},当前农场币:{point + totalPoint}"
|
||||||
await g_pSqlManager.updateUserPointByUid(uid, p + totalPoint)
|
|
||||||
|
|
||||||
if name:
|
|
||||||
return f"成功出售{name},获得农场币:{totalPoint}"
|
|
||||||
else:
|
else:
|
||||||
return f"成功出售所有作物,获得农场币:{totalPoint}"
|
return f"成功出售{name},获得农场币:{totalPoint},当前农场币:{point + totalPoint}"
|
||||||
|
|
||||||
g_pShopManager = CShopManager()
|
g_pShopManager = CShopManager()
|
||||||
|
|||||||
88
request.py
@ -1,31 +1,87 @@
|
|||||||
|
from email.mime import base
|
||||||
from unittest import result
|
from unittest import result
|
||||||
|
|
||||||
import requests
|
import httpx
|
||||||
|
|
||||||
|
from zhenxun.configs.config import Config
|
||||||
|
from zhenxun.services.log import logger
|
||||||
|
|
||||||
|
|
||||||
class CRequestManager:
|
class CRequestManager:
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def post(cls, url, json_data=None, form_data=None):
|
async def download(cls, url: str, savePath: str, fileName: str) -> bool:
|
||||||
"""发送 POST 请求(支持 JSON/Form-Data 格式)"""
|
"""下载文件到指定路径
|
||||||
|
|
||||||
|
Args:
|
||||||
|
url (str): 文件的下载链接
|
||||||
|
savePath (str): 保存文件的文件夹路径
|
||||||
|
fileName (str): 保存后的文件名
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: 是否下载成功
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
headers = {"Content-Type": "application/json"} if json_data else None
|
async with httpx.AsyncClient(timeout=10.0) as client:
|
||||||
response = requests.post(
|
response = await client.get(url)
|
||||||
url,
|
if response.status_code == 200:
|
||||||
json=json_data,
|
fullPath = savePath.rstrip("/") + "/" + fileName
|
||||||
data=form_data,
|
with open(fullPath, "wb") as f:
|
||||||
headers=headers,
|
f.write(response.content)
|
||||||
timeout=5
|
return True
|
||||||
)
|
else:
|
||||||
response.raise_for_status()
|
logger.warning(f"文件下载失败: HTTP {response.status_code} {response.text}")
|
||||||
return response.json()
|
return False
|
||||||
except requests.exceptions.RequestException as e:
|
except Exception as e:
|
||||||
print(f"请求失败: {e}")
|
logger.warning(f"下载文件异常: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def post(cls, endpoint: str, name: str = "", jsonData: dict = None, formData: dict = None) -> dict:
|
||||||
|
"""发送POST请求到指定接口,供其他方法统一调用
|
||||||
|
|
||||||
|
Args:
|
||||||
|
endpoint (str): 请求的接口路径
|
||||||
|
name (str, optional): 操作名称用于日志记录
|
||||||
|
jsonData (dict, optional): 以JSON格式发送的数据
|
||||||
|
formData (dict, optional): 以表单格式发送的数据
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
ValueError: 当jsonData和formData都未提供时抛出
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict: 返回请求结果的JSON数据
|
||||||
|
"""
|
||||||
|
if jsonData is None and formData is None:
|
||||||
|
raise ValueError("post请求必须提供jsonData或formData其中之一")
|
||||||
|
|
||||||
|
baseUrl = Config.get_config("zhenxun_plugin_farm", "服务地址")
|
||||||
|
|
||||||
|
url = f"{baseUrl.rstrip('/')}/{endpoint.lstrip('/')}"
|
||||||
|
|
||||||
|
try:
|
||||||
|
async with httpx.AsyncClient(timeout=5.0) as client:
|
||||||
|
if jsonData is not None:
|
||||||
|
response = await client.post(url, json=jsonData)
|
||||||
|
else:
|
||||||
|
response = await client.post(url, data=formData)
|
||||||
|
|
||||||
|
if response.status_code == 200:
|
||||||
|
return response.json()
|
||||||
|
else:
|
||||||
|
logger.warning(f"真寻农场{name}请求失败: HTTP {response.status_code} {response.text}")
|
||||||
|
return {}
|
||||||
|
except httpx.RequestError as e:
|
||||||
|
logger.warning(f"真寻农场{name}请求异常: {e}")
|
||||||
return {}
|
return {}
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"真寻农场{name}处理异常: {e}")
|
||||||
|
return {}
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
async def sign(cls, uid: str) -> str:
|
async def sign(cls, uid: str) -> str:
|
||||||
a = await cls.post("http://diuse.work:9099/testPost", json_data={"level":3})
|
a = await cls.post("http://diuse.work:9099/testPost", jsonData={"level":3})
|
||||||
|
|
||||||
result = ""
|
result = ""
|
||||||
|
|
||||||
|
|||||||
BIN
resource/plant/水稻/0.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 7.2 KiB After Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 7.1 KiB After Width: | Height: | Size: 7.1 KiB |