koishi-plugin-wordle-game 2.2.3 → 2.2.5

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.
package/lib/index.d.ts CHANGED
@@ -126,6 +126,7 @@ export interface PlayerRecord {
126
126
  wordGuessCount: number;
127
127
  stats: PlayerStats;
128
128
  fastestGuessTime: Record<string, number>;
129
+ extraCiyingRankInfo: ExtraCiyingRankInfo;
129
130
  }
130
131
  interface PlayerStats {
131
132
  经典?: WinLoseStats;
@@ -149,5 +150,27 @@ interface WinLoseStats {
149
150
  win: number;
150
151
  lose: number;
151
152
  }
153
+ interface ExtraCiyingRankInfo {
154
+ successCountIn1HardMode: number;
155
+ successCountIn1Mode: number;
156
+ successCountIn2Mode: number;
157
+ successCountIn3Mode: number;
158
+ successCountIn4Mode: number;
159
+ winIn1HardMode: number;
160
+ winIn1Mode: number;
161
+ winIn2Mode: number;
162
+ winIn3Mode: number;
163
+ winIn4Mode: number;
164
+ loseIn1HardMode: number;
165
+ loseIn1Mode: number;
166
+ loseIn2Mode: number;
167
+ loseIn3Mode: number;
168
+ loseIn4Mode: number;
169
+ fastestGuessTimeIn1HardMode: number;
170
+ fastestGuessTimeIn1Mode: number;
171
+ fastestGuessTimeIn2Mode: number;
172
+ fastestGuessTimeIn3Mode: number;
173
+ fastestGuessTimeIn4Mode: number;
174
+ }
152
175
  export declare function apply(ctx: Context, config: Config): Promise<void>;
153
176
  export {};
package/lib/index.js CHANGED
@@ -147,6 +147,28 @@ exports.Config = koishi_1.Schema.intersect([
147
147
  }),
148
148
  ])
149
149
  ]);
150
+ const initialExtraCiyingRankInfo = {
151
+ "successCountIn1HardMode": 0,
152
+ "successCountIn1Mode": 0,
153
+ "successCountIn2Mode": 0,
154
+ "successCountIn3Mode": 0,
155
+ "successCountIn4Mode": 0,
156
+ "winIn1HardMode": 0,
157
+ "winIn1Mode": 0,
158
+ "winIn2Mode": 0,
159
+ "winIn3Mode": 0,
160
+ "winIn4Mode": 0,
161
+ "loseIn1HardMode": 0,
162
+ "loseIn1Mode": 0,
163
+ "loseIn2Mode": 0,
164
+ "loseIn3Mode": 0,
165
+ "loseIn4Mode": 0,
166
+ "fastestGuessTimeIn1HardMode": 0,
167
+ "fastestGuessTimeIn1Mode": 0,
168
+ "fastestGuessTimeIn2Mode": 0,
169
+ "fastestGuessTimeIn3Mode": 0,
170
+ "fastestGuessTimeIn4Mode": 0
171
+ };
150
172
  const initialStats = {
151
173
  经典: { win: 0, lose: 0 },
152
174
  Lewdle: { win: 0, lose: 0 },
@@ -305,6 +327,7 @@ async function apply(ctx, config) {
305
327
  wordGuessCount: 'unsigned',
306
328
  stats: { type: 'json', initial: initialStats },
307
329
  fastestGuessTime: { type: 'json', initial: initialFastestGuessTime },
330
+ extraCiyingRankInfo: { type: 'json', initial: initialExtraCiyingRankInfo },
308
331
  }, {
309
332
  primary: 'id',
310
333
  autoInc: true,
@@ -1275,17 +1298,45 @@ async function apply(ctx, config) {
1275
1298
  finalSettlementString = await processNonZeroMoneyPlayers(channelId, platform);
1276
1299
  }
1277
1300
  // 玩家记录赢
1278
- await updatePlayerRecordsWin(channelId, gameInfo);
1301
+ await updatePlayerRecordsWin(channelId, gameInfo); // db*
1279
1302
  // 增加该玩家猜出单词的次数
1280
1303
  const [playerRecord] = await ctx.database.get('wordle_player_records', { userId });
1281
1304
  // 更新最快用时
1282
1305
  if (timeDifferenceInSeconds < playerRecord.fastestGuessTime[gameInfo.gameMode] || playerRecord.fastestGuessTime[gameInfo.gameMode] === 0) {
1283
1306
  playerRecord.fastestGuessTime[gameInfo.gameMode] = Math.floor(timeDifferenceInSeconds);
1284
1307
  }
1285
- await ctx.database.set('wordle_player_records', { userId }, {
1308
+ if (gameInfo.gameMode === '词影') {
1309
+ if (gameInfo.wordlesNum === 1) {
1310
+ if (gameInfo.isHardMode) {
1311
+ playerRecord.extraCiyingRankInfo.successCountIn1HardMode += 1;
1312
+ if (timeDifferenceInSeconds < playerRecord.extraCiyingRankInfo.fastestGuessTimeIn1HardMode || playerRecord.extraCiyingRankInfo.fastestGuessTimeIn1HardMode === 0) {
1313
+ playerRecord.extraCiyingRankInfo.fastestGuessTimeIn1HardMode = Math.floor(timeDifferenceInSeconds);
1314
+ }
1315
+ }
1316
+ else {
1317
+ playerRecord.extraCiyingRankInfo.successCountIn1Mode += 1;
1318
+ if (timeDifferenceInSeconds < playerRecord.extraCiyingRankInfo.fastestGuessTimeIn1Mode || playerRecord.extraCiyingRankInfo.fastestGuessTimeIn1Mode === 0) {
1319
+ playerRecord.extraCiyingRankInfo.fastestGuessTimeIn1Mode = Math.floor(timeDifferenceInSeconds);
1320
+ }
1321
+ }
1322
+ }
1323
+ else if (gameInfo.wordlesNum >= 2 && gameInfo.wordlesNum <= 4) {
1324
+ const extraCiyingRankInfoKey = `successCountIn${gameInfo.wordlesNum}Mode`;
1325
+ const extraCiyingRankInfoKeyFastestGuessTimeIn = `fastestGuessTimeIn${gameInfo.wordlesNum}Mode`;
1326
+ playerRecord.extraCiyingRankInfo[extraCiyingRankInfoKey] += 1;
1327
+ if (timeDifferenceInSeconds < playerRecord.extraCiyingRankInfo[extraCiyingRankInfoKeyFastestGuessTimeIn] || playerRecord.extraCiyingRankInfo[extraCiyingRankInfoKeyFastestGuessTimeIn] === 0) {
1328
+ playerRecord.extraCiyingRankInfo[extraCiyingRankInfoKeyFastestGuessTimeIn] = Math.floor(timeDifferenceInSeconds);
1329
+ }
1330
+ }
1331
+ }
1332
+ const updateData = {
1286
1333
  wordGuessCount: playerRecord.wordGuessCount + 1,
1287
1334
  fastestGuessTime: playerRecord.fastestGuessTime
1288
- });
1335
+ };
1336
+ if (gameInfo.gameMode === '词影') {
1337
+ updateData['extraCiyingRankInfo'] = playerRecord.extraCiyingRankInfo;
1338
+ }
1339
+ await ctx.database.set('wordle_player_records', { userId: userId }, updateData);
1289
1340
  const processedResult = wordlesNum > 1 ? `\n${await processExtraGameRecords(channelId)}` : '';
1290
1341
  await endGame(channelId);
1291
1342
  const gameDuration = calculateGameDuration(gameInfo.timestamp, timestamp);
@@ -1736,6 +1787,9 @@ ${rankType.map((type, index) => `${index + 1}. ${type}`).join('\n')}
1736
1787
  if (type === '总') {
1737
1788
  rankType3 = ["胜场", "输场"];
1738
1789
  }
1790
+ else if (type === '词影') {
1791
+ rankType3 = ["猜出次数", "胜场", "输场", "最快用时"];
1792
+ }
1739
1793
  else {
1740
1794
  rankType3 = ["胜场", "输场", "最快用时"];
1741
1795
  }
@@ -1810,28 +1864,133 @@ ${rankType3.map((type, index) => `${index + 1}. ${type}`).join('\n')}
1810
1864
  // 注册胜场、输场、用时排行榜指令
1811
1865
  rankType4.forEach((type) => {
1812
1866
  ctx.command(`wordleGame.排行榜.${type}.胜场 [number:number]`, `查看${type}胜场排行榜`)
1813
- .action(async ({ session }, number = config.defaultMaxLeaderboardEntries) => {
1867
+ .option('hard', '--hard 查看困难模式', { fallback: false })
1868
+ .option('wordles', '--wordles <value:number> 查看多猜测模式', { fallback: 0 })
1869
+ .action(async ({ session, options }, number = config.defaultMaxLeaderboardEntries) => {
1814
1870
  const { channelId, username, userId } = session;
1815
1871
  // 更新玩家记录表中的用户名
1816
1872
  await updateNameInPlayerRecord(userId, username);
1873
+ if (typeof number !== 'number' || isNaN(number) || number < 0) {
1874
+ return '请输入大于等于 0 的数字作为排行榜的参数。';
1875
+ }
1876
+ if (type === '词影' && options.wordles !== 0 || type === '词影' && options.hard) {
1877
+ if (options.wordles === 0) {
1878
+ options.wordles = 1;
1879
+ }
1880
+ if (typeof options.wordles !== 'number' || options.wordles < 1 || options.wordles > 4) {
1881
+ return await sendMessage(session, `【@${username}】\n词影可查看的多猜测排行榜应在 1 ~ 4 之间!`);
1882
+ }
1883
+ return await getWinCountLeaderboardForCiying(session, options.wordles, `玩家胜场排行榜(词影 x${options.wordles}${options.hard && options.wordles === 1 ? '(困难)' : ''})`, number, options.hard);
1884
+ }
1817
1885
  return await sendMessage(session, await getLeaderboardWinOrLose(type, number, 'win', '胜场'));
1818
1886
  });
1819
1887
  ctx.command(`wordleGame.排行榜.${type}.输场 [number:number]`, `查看${type}输场排行榜`)
1820
- .action(async ({ session }, number = config.defaultMaxLeaderboardEntries) => {
1888
+ .option('hard', '--hard 查看困难模式', { fallback: false })
1889
+ .option('wordles', '--wordles <value:number> 查看多猜测模式', { fallback: 0 })
1890
+ .action(async ({ session, options }, number = config.defaultMaxLeaderboardEntries) => {
1821
1891
  const { channelId, username, userId } = session;
1822
1892
  // 更新玩家记录表中的用户名
1823
1893
  await updateNameInPlayerRecord(userId, username);
1894
+ if (typeof number !== 'number' || isNaN(number) || number < 0) {
1895
+ return '请输入大于等于 0 的数字作为排行榜的参数。';
1896
+ }
1897
+ if (type === '词影' && options.wordles !== 0 || type === '词影' && options.hard) {
1898
+ if (options.wordles === 0) {
1899
+ options.wordles = 1;
1900
+ }
1901
+ if (typeof options.wordles !== 'number' || options.wordles < 1 || options.wordles > 4) {
1902
+ return await sendMessage(session, `【@${username}】\n词影可查看的多猜测排行榜应在 1 ~ 4 之间!`);
1903
+ }
1904
+ return await getLoseCountLeaderboardForCiying(session, options.wordles, `玩家输场排行榜(词影 x${options.wordles}${options.hard && options.wordles === 1 ? '(困难)' : ''})`, number, options.hard);
1905
+ }
1824
1906
  return await sendMessage(session, await getLeaderboardWinOrLose(type, number, 'lose', '输场'));
1825
1907
  });
1826
1908
  ctx.command(`wordleGame.排行榜.${type}.最快用时 [number:number]`, `查看${type}最快用时排行榜`)
1827
- .action(async ({ session }, number = config.defaultMaxLeaderboardEntries) => {
1909
+ .option('hard', '--hard 查看困难模式', { fallback: false })
1910
+ .option('wordles', '--wordles <value:number> 查看多猜测模式', { fallback: 0 })
1911
+ .action(async ({ session, options }, number = config.defaultMaxLeaderboardEntries) => {
1828
1912
  const { channelId, username, userId } = session;
1829
1913
  // 更新玩家记录表中的用户名
1830
1914
  await updateNameInPlayerRecord(userId, username);
1915
+ if (typeof number !== 'number' || isNaN(number) || number < 0) {
1916
+ return '请输入大于等于 0 的数字作为排行榜的参数。';
1917
+ }
1918
+ if (type === '词影' && options.wordles !== 0 || type === '词影' && options.hard) {
1919
+ if (options.wordles === 0) {
1920
+ options.wordles = 1;
1921
+ }
1922
+ if (typeof options.wordles !== 'number' || options.wordles < 1 || options.wordles > 4) {
1923
+ return await sendMessage(session, `【@${username}】\n词影可查看的多猜测排行榜应在 1 ~ 4 之间!`);
1924
+ }
1925
+ return await getFastestGuessTimeLeaderboardForCiying(session, options.wordles, `玩家最快用时排行榜(词影 x${options.wordles}${options.hard && options.wordles === 1 ? '(困难)' : ''})`, number, options.hard);
1926
+ }
1831
1927
  return await sendMessage(session, await getLeaderboardFastestGuessTime(type, number));
1832
1928
  });
1833
1929
  });
1930
+ ctx.command('wordleGame.排行榜.词影.猜出次数 [number:number]', '查看玩家猜出次数排行榜(词影)') // db*
1931
+ .option('hard', '--hard 查看困难模式', { fallback: false })
1932
+ .option('wordles', '--wordles <value:number> 查看多猜测模式', { fallback: 1 })
1933
+ .action(async ({ session, options }, number = config.defaultMaxLeaderboardEntries) => {
1934
+ const { channelId, username, userId } = session;
1935
+ // 更新玩家记录表中的用户名
1936
+ await updateNameInPlayerRecord(userId, username);
1937
+ if (typeof number !== 'number' || isNaN(number) || number < 0) {
1938
+ return '请输入大于等于 0 的数字作为排行榜的参数。';
1939
+ }
1940
+ if (typeof options.wordles !== 'number' || options.wordles < 1 || options.wordles > 4) {
1941
+ return await sendMessage(session, `【@${username}】\n词影可查看的多猜测排行榜应在 1 ~ 4 之间!`);
1942
+ }
1943
+ return await getCiyingSuccessCountLeaderboardForCiying(session, options.wordles, 'successCount', `玩家猜出次数排行榜(词影 x${options.wordles}${options.hard && options.wordles === 1 ? '(困难)' : ''})`, number, options.hard);
1944
+ });
1834
1945
  // ch*
1946
+ async function getWinCountLeaderboardForCiying(session, wordlesNum, title, number, isHardMode) {
1947
+ const getPlayers = await ctx.database.get('wordle_player_records', {});
1948
+ let sortedPlayers;
1949
+ let result = '';
1950
+ let winCountField = isHardMode ? 'winIn1HardMode' : 'winIn1Mode';
1951
+ if (wordlesNum >= 2 && wordlesNum <= 4) {
1952
+ winCountField = `winIn${wordlesNum}Mode`;
1953
+ }
1954
+ sortedPlayers = getPlayers.sort((a, b) => b.extraCiyingRankInfo[winCountField] - a.extraCiyingRankInfo[winCountField]);
1955
+ const topPlayers = sortedPlayers.slice(0, number);
1956
+ result = `${title}:\n`;
1957
+ topPlayers.forEach((player, index) => {
1958
+ result += `${index + 1}. ${player.username}:${player.extraCiyingRankInfo[winCountField]} 次\n`;
1959
+ });
1960
+ return await sendMessage(session, result);
1961
+ }
1962
+ async function getLoseCountLeaderboardForCiying(session, wordlesNum, title, number, isHardMode) {
1963
+ const getPlayers = await ctx.database.get('wordle_player_records', {});
1964
+ let sortedPlayers;
1965
+ let result = '';
1966
+ let loseCountField = isHardMode ? 'loseIn1HardMode' : 'loseIn1Mode';
1967
+ if (wordlesNum >= 2 && wordlesNum <= 4) {
1968
+ loseCountField = `loseIn${wordlesNum}Mode`;
1969
+ }
1970
+ sortedPlayers = getPlayers.sort((a, b) => b.extraCiyingRankInfo[loseCountField] - a.extraCiyingRankInfo[loseCountField]);
1971
+ const topPlayers = sortedPlayers.slice(0, number);
1972
+ result = `${title}:\n`;
1973
+ topPlayers.forEach((player, index) => {
1974
+ result += `${index + 1}. ${player.username}:${player.extraCiyingRankInfo[loseCountField]} 次\n`;
1975
+ });
1976
+ return await sendMessage(session, result);
1977
+ }
1978
+ async function getFastestGuessTimeLeaderboardForCiying(session, wordlesNum, title, number, isHardMode) {
1979
+ const getPlayers = await ctx.database.get('wordle_player_records', {});
1980
+ let sortedPlayers;
1981
+ let result = '';
1982
+ let fastestGuessTimeField = isHardMode ? 'fastestGuessTimeIn1HardMode' : 'fastestGuessTimeIn1Mode';
1983
+ if (wordlesNum >= 2 && wordlesNum <= 4) {
1984
+ fastestGuessTimeField = `fastestGuessTimeIn${wordlesNum}Mode`;
1985
+ }
1986
+ sortedPlayers = getPlayers.sort((a, b) => a.extraCiyingRankInfo[fastestGuessTimeField] - b.extraCiyingRankInfo[fastestGuessTimeField]);
1987
+ const topPlayers = sortedPlayers.slice(0, number);
1988
+ result = `${title}:\n`;
1989
+ topPlayers.forEach((player, index) => {
1990
+ result += `${index + 1}. ${player.username}:${formatGameDuration2(player.extraCiyingRankInfo[fastestGuessTimeField])}\n`;
1991
+ });
1992
+ return await sendMessage(session, result);
1993
+ }
1835
1994
  async function generateHandlePinyinsImage(pinyinsHtml) {
1836
1995
  const browser = ctx.puppeteer.browser;
1837
1996
  const context = await browser.createBrowserContext();
@@ -2420,6 +2579,22 @@ ${rankType3.map((type, index) => `${index + 1}. ${type}`).join('\n')}
2420
2579
  await setGuessRunningStatus(channelId, false),
2421
2580
  ]);
2422
2581
  }
2582
+ async function getCiyingSuccessCountLeaderboardForCiying(session, wordlesNum, sortField, title, number, isHardMode) {
2583
+ const getPlayers = await ctx.database.get('wordle_player_records', {});
2584
+ let sortedPlayers;
2585
+ let result = '';
2586
+ let successCountField = isHardMode ? 'successCountIn1HardMode' : 'successCountIn1Mode';
2587
+ if (wordlesNum >= 2 && wordlesNum <= 4) {
2588
+ successCountField = `successCountIn${wordlesNum}Mode`;
2589
+ }
2590
+ sortedPlayers = getPlayers.sort((a, b) => b.extraCiyingRankInfo[successCountField] - a.extraCiyingRankInfo[successCountField]);
2591
+ const topPlayers = sortedPlayers.slice(0, number);
2592
+ result = `${title}:\n`;
2593
+ topPlayers.forEach((player, index) => {
2594
+ result += `${index + 1}. ${player.username}:${player.extraCiyingRankInfo[successCountField]} 次\n`;
2595
+ });
2596
+ return await sendMessage(session, result);
2597
+ }
2423
2598
  async function getLeaderboard(session, type, sortField, title, number) {
2424
2599
  const getPlayers = await ctx.database.get('wordle_player_records', {});
2425
2600
  const sortedPlayers = getPlayers.sort((a, b) => b[sortField] - a[sortField]);
@@ -2437,10 +2612,28 @@ ${rankType3.map((type, index) => `${index + 1}. ${type}`).join('\n')}
2437
2612
  const updatedLose = playerInfo.lose + 1;
2438
2613
  const gameMode = gameInfo.gameMode;
2439
2614
  playerInfo.stats[gameMode].lose += 1;
2440
- await ctx.database.set('wordle_player_records', { userId: player.userId }, {
2615
+ if (gameInfo.gameMode === '词影') {
2616
+ if (gameInfo.wordlesNum === 1) {
2617
+ if (gameInfo.isHardMode) {
2618
+ playerInfo.extraCiyingRankInfo.loseIn1HardMode += 1;
2619
+ }
2620
+ else {
2621
+ playerInfo.extraCiyingRankInfo.loseIn1Mode += 1;
2622
+ }
2623
+ }
2624
+ else if (gameInfo.wordlesNum >= 2 && gameInfo.wordlesNum <= 4) {
2625
+ const extraCiyingRankInfoKey = `loseIn${gameInfo.wordlesNum}Mode`;
2626
+ playerInfo.extraCiyingRankInfo[extraCiyingRankInfoKey] += 1;
2627
+ }
2628
+ }
2629
+ const updateData = {
2441
2630
  stats: playerInfo.stats,
2442
2631
  lose: updatedLose
2443
- });
2632
+ };
2633
+ if (gameInfo.gameMode === '词影') {
2634
+ updateData['extraCiyingRankInfo'] = playerInfo.extraCiyingRankInfo;
2635
+ }
2636
+ await ctx.database.set('wordle_player_records', { userId: player.userId }, updateData);
2444
2637
  }
2445
2638
  }
2446
2639
  async function updatePlayerRecordsWin(channelId, gameInfo) {
@@ -2450,10 +2643,28 @@ ${rankType3.map((type, index) => `${index + 1}. ${type}`).join('\n')}
2450
2643
  const updatedWin = playerInfo.win + 1;
2451
2644
  const gameMode = gameInfo.gameMode;
2452
2645
  playerInfo.stats[gameMode].win += 1;
2453
- await ctx.database.set('wordle_player_records', { userId: player.userId }, {
2646
+ if (gameInfo.gameMode === '词影') {
2647
+ if (gameInfo.wordlesNum === 1) {
2648
+ if (gameInfo.isHardMode) {
2649
+ playerInfo.extraCiyingRankInfo.winIn1HardMode += 1;
2650
+ }
2651
+ else {
2652
+ playerInfo.extraCiyingRankInfo.winIn1Mode += 1;
2653
+ }
2654
+ }
2655
+ else if (gameInfo.wordlesNum >= 2 && gameInfo.wordlesNum <= 4) {
2656
+ const extraCiyingRankInfoKey = `winIn${gameInfo.wordlesNum}Mode`;
2657
+ playerInfo.extraCiyingRankInfo[extraCiyingRankInfoKey] += 1;
2658
+ }
2659
+ }
2660
+ const updateData = {
2454
2661
  stats: playerInfo.stats,
2455
2662
  win: updatedWin
2456
- });
2663
+ };
2664
+ if (gameInfo.gameMode === '词影') {
2665
+ updateData['extraCiyingRankInfo'] = playerInfo.extraCiyingRankInfo;
2666
+ }
2667
+ await ctx.database.set('wordle_player_records', { userId: player.userId }, updateData);
2457
2668
  }
2458
2669
  }
2459
2670
  async function processNonZeroMoneyPlayers(channelId, platform) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-wordle-game",
3
3
  "description": "欢迎来到 [Wordle](https://www.nytimes.com/games/wordle/index.html) | [汉兜](https://handle.antfu.me/) | [词影](https://cy.surprising.studio/) |... 猜单词|猜成语|猜数字|猜数学方程式|... 的小游戏,包含多种词库、多种主题、多种游戏设置和排行榜系统。",
4
- "version": "2.2.3",
4
+ "version": "2.2.5",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [