claude-scope 0.4.0 → 0.4.2

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.
Files changed (2) hide show
  1. package/dist/claude-scope.cjs +225 -31
  2. package/package.json +1 -1
@@ -969,6 +969,116 @@ function countSuits(cards) {
969
969
  }
970
970
  return counts;
971
971
  }
972
+ function findCardsOfRank(cards, targetRank) {
973
+ const indices = [];
974
+ for (let i = 0; i < cards.length; i++) {
975
+ if (getRankValue(cards[i].rank) === targetRank) {
976
+ indices.push(i);
977
+ }
978
+ }
979
+ return indices;
980
+ }
981
+ function findCardsOfSuit(cards, targetSuit) {
982
+ const indices = [];
983
+ for (let i = 0; i < cards.length; i++) {
984
+ if (cards[i].suit === targetSuit) {
985
+ indices.push(i);
986
+ }
987
+ }
988
+ return indices;
989
+ }
990
+ function findFlushSuit(cards) {
991
+ const suitCounts = countSuits(cards);
992
+ for (const [suit, count] of suitCounts.entries()) {
993
+ if (count >= 5) return suit;
994
+ }
995
+ return null;
996
+ }
997
+ function getStraightIndices(cards, highCard) {
998
+ const uniqueValues = /* @__PURE__ */ new Set();
999
+ const cardIndicesByRank = /* @__PURE__ */ new Map();
1000
+ for (let i = 0; i < cards.length; i++) {
1001
+ const value = getRankValue(cards[i].rank);
1002
+ if (!cardIndicesByRank.has(value)) {
1003
+ cardIndicesByRank.set(value, []);
1004
+ uniqueValues.add(value);
1005
+ }
1006
+ cardIndicesByRank.get(value).push(i);
1007
+ }
1008
+ const sortedValues = Array.from(uniqueValues).sort((a, b) => b - a);
1009
+ if (sortedValues.includes(14)) {
1010
+ sortedValues.push(1);
1011
+ }
1012
+ for (let i = 0; i <= sortedValues.length - 5; i++) {
1013
+ const current = sortedValues[i];
1014
+ const next1 = sortedValues[i + 1];
1015
+ const next2 = sortedValues[i + 2];
1016
+ const next3 = sortedValues[i + 3];
1017
+ const next4 = sortedValues[i + 4];
1018
+ if (current - next1 === 1 && current - next2 === 2 && current - next3 === 3 && current - next4 === 4) {
1019
+ if (current === highCard) {
1020
+ const indices = [];
1021
+ indices.push(cardIndicesByRank.get(current)[0]);
1022
+ indices.push(cardIndicesByRank.get(next1)[0]);
1023
+ indices.push(cardIndicesByRank.get(next2)[0]);
1024
+ indices.push(cardIndicesByRank.get(next3)[0]);
1025
+ indices.push(cardIndicesByRank.get(next4)[0]);
1026
+ return indices;
1027
+ }
1028
+ }
1029
+ }
1030
+ return [];
1031
+ }
1032
+ function getStraightFlushHighCard(cards, suit) {
1033
+ const suitCards = cards.filter((c) => c.suit === suit);
1034
+ return getStraightHighCard(suitCards);
1035
+ }
1036
+ function getStraightFlushIndices(cards, highCard, suit) {
1037
+ const suitCards = cards.filter((c) => c.suit === suit);
1038
+ const suitCardIndices = [];
1039
+ const indexMap = /* @__PURE__ */ new Map();
1040
+ for (let i = 0; i < cards.length; i++) {
1041
+ if (cards[i].suit === suit) {
1042
+ indexMap.set(suitCardIndices.length, i);
1043
+ suitCardIndices.push(cards[i]);
1044
+ }
1045
+ }
1046
+ const indices = getStraightIndices(suitCardIndices, highCard);
1047
+ return indices.map((idx) => indexMap.get(idx));
1048
+ }
1049
+ function getFullHouseIndices(cards) {
1050
+ const rankCounts = countRanks(cards);
1051
+ let tripsRank = 0;
1052
+ for (const [rank, count] of rankCounts.entries()) {
1053
+ if (count === 3) {
1054
+ tripsRank = rank;
1055
+ break;
1056
+ }
1057
+ }
1058
+ let pairRank = 0;
1059
+ for (const [rank, count] of rankCounts.entries()) {
1060
+ if (count >= 2 && rank !== tripsRank) {
1061
+ pairRank = rank;
1062
+ break;
1063
+ }
1064
+ }
1065
+ if (pairRank === 0) {
1066
+ const tripsRanks = [];
1067
+ for (const [rank, count] of rankCounts.entries()) {
1068
+ if (count === 3) {
1069
+ tripsRanks.push(rank);
1070
+ }
1071
+ }
1072
+ if (tripsRanks.length >= 2) {
1073
+ tripsRanks.sort((a, b) => b - a);
1074
+ tripsRank = tripsRanks[0];
1075
+ pairRank = tripsRanks[1];
1076
+ }
1077
+ }
1078
+ const tripsIndices = findCardsOfRank(cards, tripsRank);
1079
+ const pairIndices = findCardsOfRank(cards, pairRank);
1080
+ return [...tripsIndices.slice(0, 3), ...pairIndices.slice(0, 2)];
1081
+ }
972
1082
  function isFlush(cards) {
973
1083
  const suitCounts = countSuits(cards);
974
1084
  for (const count of suitCounts.values()) {
@@ -1017,6 +1127,41 @@ function getPairCount(cards) {
1017
1127
  }
1018
1128
  return pairCount;
1019
1129
  }
1130
+ function getMostCommonRank(cards) {
1131
+ const rankCounts = countRanks(cards);
1132
+ let bestRank = 0;
1133
+ let bestCount = 0;
1134
+ for (const [rank, count] of rankCounts.entries()) {
1135
+ if (count > bestCount) {
1136
+ bestCount = count;
1137
+ bestRank = rank;
1138
+ }
1139
+ }
1140
+ return bestRank > 0 ? bestRank : null;
1141
+ }
1142
+ function getTwoPairRanks(cards) {
1143
+ const rankCounts = countRanks(cards);
1144
+ const pairRanks = [];
1145
+ for (const [rank, count] of rankCounts.entries()) {
1146
+ if (count >= 2) {
1147
+ pairRanks.push(rank);
1148
+ }
1149
+ }
1150
+ pairRanks.sort((a, b) => b - a);
1151
+ return pairRanks.slice(0, 2);
1152
+ }
1153
+ function getHighestCardIndex(cards) {
1154
+ let highestIdx = 0;
1155
+ let highestValue = 0;
1156
+ for (let i = 0; i < cards.length; i++) {
1157
+ const value = getRankValue(cards[i].rank);
1158
+ if (value > highestValue) {
1159
+ highestValue = value;
1160
+ highestIdx = i;
1161
+ }
1162
+ }
1163
+ return highestIdx;
1164
+ }
1020
1165
  function evaluateHand(hole, board) {
1021
1166
  const allCards = [...hole, ...board];
1022
1167
  const flush = isFlush(allCards);
@@ -1024,33 +1169,59 @@ function evaluateHand(hole, board) {
1024
1169
  const maxCount = getMaxCount(allCards);
1025
1170
  const pairCount = getPairCount(allCards);
1026
1171
  if (flush && straightHighCard === 14) {
1027
- return { rank: 10 /* RoyalFlush */, ...HAND_DISPLAY[10 /* RoyalFlush */] };
1172
+ const flushSuit = findFlushSuit(allCards);
1173
+ const sfHighCard = getStraightFlushHighCard(allCards, flushSuit);
1174
+ if (sfHighCard === 14) {
1175
+ const participatingCards = getStraightFlushIndices(allCards, 14, flushSuit);
1176
+ return { rank: 10 /* RoyalFlush */, ...HAND_DISPLAY[10 /* RoyalFlush */], participatingCards };
1177
+ }
1028
1178
  }
1029
- if (flush && straightHighCard !== null) {
1030
- return { rank: 9 /* StraightFlush */, ...HAND_DISPLAY[9 /* StraightFlush */] };
1179
+ if (flush) {
1180
+ const flushSuit = findFlushSuit(allCards);
1181
+ const sfHighCard = getStraightFlushHighCard(allCards, flushSuit);
1182
+ if (sfHighCard !== null) {
1183
+ const participatingCards = getStraightFlushIndices(allCards, sfHighCard, flushSuit);
1184
+ return { rank: 9 /* StraightFlush */, ...HAND_DISPLAY[9 /* StraightFlush */], participatingCards };
1185
+ }
1031
1186
  }
1032
1187
  if (maxCount === 4) {
1033
- return { rank: 8 /* FourOfAKind */, ...HAND_DISPLAY[8 /* FourOfAKind */] };
1188
+ const rank = getMostCommonRank(allCards);
1189
+ const participatingCards = findCardsOfRank(allCards, rank);
1190
+ return { rank: 8 /* FourOfAKind */, ...HAND_DISPLAY[8 /* FourOfAKind */], participatingCards };
1034
1191
  }
1035
1192
  if (maxCount === 3 && pairCount >= 1) {
1036
- return { rank: 7 /* FullHouse */, ...HAND_DISPLAY[7 /* FullHouse */] };
1193
+ const participatingCards = getFullHouseIndices(allCards);
1194
+ return { rank: 7 /* FullHouse */, ...HAND_DISPLAY[7 /* FullHouse */], participatingCards };
1037
1195
  }
1038
1196
  if (flush) {
1039
- return { rank: 6 /* Flush */, ...HAND_DISPLAY[6 /* Flush */] };
1197
+ const flushSuit = findFlushSuit(allCards);
1198
+ const suitIndices = findCardsOfSuit(allCards, flushSuit);
1199
+ const participatingCards = suitIndices.slice(0, 5);
1200
+ return { rank: 6 /* Flush */, ...HAND_DISPLAY[6 /* Flush */], participatingCards };
1040
1201
  }
1041
1202
  if (straightHighCard !== null) {
1042
- return { rank: 5 /* Straight */, ...HAND_DISPLAY[5 /* Straight */] };
1203
+ const participatingCards = getStraightIndices(allCards, straightHighCard);
1204
+ return { rank: 5 /* Straight */, ...HAND_DISPLAY[5 /* Straight */], participatingCards };
1043
1205
  }
1044
1206
  if (maxCount === 3) {
1045
- return { rank: 4 /* ThreeOfAKind */, ...HAND_DISPLAY[4 /* ThreeOfAKind */] };
1207
+ const rank = getMostCommonRank(allCards);
1208
+ const participatingCards = findCardsOfRank(allCards, rank);
1209
+ return { rank: 4 /* ThreeOfAKind */, ...HAND_DISPLAY[4 /* ThreeOfAKind */], participatingCards };
1046
1210
  }
1047
1211
  if (pairCount >= 2) {
1048
- return { rank: 3 /* TwoPair */, ...HAND_DISPLAY[3 /* TwoPair */] };
1212
+ const [rank1, rank2] = getTwoPairRanks(allCards);
1213
+ const pair1Indices = findCardsOfRank(allCards, rank1);
1214
+ const pair2Indices = findCardsOfRank(allCards, rank2);
1215
+ const participatingCards = [...pair1Indices, ...pair2Indices];
1216
+ return { rank: 3 /* TwoPair */, ...HAND_DISPLAY[3 /* TwoPair */], participatingCards };
1049
1217
  }
1050
1218
  if (pairCount === 1) {
1051
- return { rank: 2 /* OnePair */, ...HAND_DISPLAY[2 /* OnePair */] };
1219
+ const rank = getMostCommonRank(allCards);
1220
+ const participatingCards = findCardsOfRank(allCards, rank);
1221
+ return { rank: 2 /* OnePair */, ...HAND_DISPLAY[2 /* OnePair */], participatingCards };
1052
1222
  }
1053
- return { rank: 1 /* HighCard */, ...HAND_DISPLAY[1 /* HighCard */] };
1223
+ const highestIdx = getHighestCardIndex(allCards);
1224
+ return { rank: 1 /* HighCard */, ...HAND_DISPLAY[1 /* HighCard */], participatingCards: [highestIdx] };
1054
1225
  }
1055
1226
 
1056
1227
  // src/widgets/poker-widget.ts
@@ -1064,10 +1235,9 @@ var PokerWidget = class extends StdinDataWidget {
1064
1235
  2
1065
1236
  // Third line (0-indexed)
1066
1237
  );
1067
- deck = null;
1068
1238
  holeCards = [];
1069
1239
  boardCards = [];
1070
- handResult = "";
1240
+ handResult = null;
1071
1241
  constructor() {
1072
1242
  super();
1073
1243
  }
@@ -1076,22 +1246,30 @@ var PokerWidget = class extends StdinDataWidget {
1076
1246
  */
1077
1247
  async update(data) {
1078
1248
  await super.update(data);
1079
- this.deck = new Deck();
1080
- const hole = [
1081
- this.deck.deal(),
1082
- this.deck.deal()
1083
- ];
1084
- const board = [
1085
- this.deck.deal(),
1086
- this.deck.deal(),
1087
- this.deck.deal(),
1088
- this.deck.deal(),
1089
- this.deck.deal()
1090
- ];
1249
+ const deck = new Deck();
1250
+ const hole = [deck.deal(), deck.deal()];
1251
+ const board = [deck.deal(), deck.deal(), deck.deal(), deck.deal(), deck.deal()];
1091
1252
  const result = evaluateHand(hole, board);
1092
- this.holeCards = hole.map((card) => this.formatCardColor(card));
1093
- this.boardCards = board.map((card) => this.formatCardColor(card));
1094
- this.handResult = `${result.name}! ${result.emoji}`;
1253
+ this.holeCards = hole.map((card) => ({
1254
+ card,
1255
+ formatted: this.formatCardColor(card)
1256
+ }));
1257
+ this.boardCards = board.map((card) => ({
1258
+ card,
1259
+ formatted: this.formatCardColor(card)
1260
+ }));
1261
+ const playerParticipates = result.participatingCards.some((idx) => idx < 2);
1262
+ if (!playerParticipates) {
1263
+ this.handResult = {
1264
+ text: `Nothing \u{1F0CF}`,
1265
+ participatingIndices: result.participatingCards
1266
+ };
1267
+ } else {
1268
+ this.handResult = {
1269
+ text: `${result.name}! ${result.emoji}`,
1270
+ participatingIndices: result.participatingCards
1271
+ };
1272
+ }
1095
1273
  }
1096
1274
  /**
1097
1275
  * Format card with appropriate color (red for ♥♦, gray for ♠♣)
@@ -1100,10 +1278,26 @@ var PokerWidget = class extends StdinDataWidget {
1100
1278
  const color = isRedSuit(card.suit) ? red : gray;
1101
1279
  return colorize(`[${formatCard(card)}]`, color);
1102
1280
  }
1281
+ /**
1282
+ * Format card based on participation in best hand
1283
+ * Participating cards: [K♠] (with brackets)
1284
+ * Non-participating cards: K♠ (spaces instead of brackets)
1285
+ */
1286
+ formatCardByParticipation(cardData, isParticipating) {
1287
+ if (isParticipating) {
1288
+ return cardData.formatted;
1289
+ } else {
1290
+ const plainText = formatCard(cardData.card);
1291
+ return ` ${plainText} `;
1292
+ }
1293
+ }
1103
1294
  renderWithData(_data, _context) {
1104
- const handStr = this.holeCards.join(" ");
1105
- const boardStr = this.boardCards.join(" ");
1106
- return `Hand: ${handStr} | Board: ${boardStr} \u2192 ${this.handResult}`;
1295
+ const participatingSet = new Set(this.handResult?.participatingIndices || []);
1296
+ const handStr = this.holeCards.map((hc, idx) => this.formatCardByParticipation(hc, participatingSet.has(idx))).join("");
1297
+ const boardStr = this.boardCards.map((bc, idx) => this.formatCardByParticipation(bc, participatingSet.has(idx + 2))).join("");
1298
+ const handLabel = colorize("Hand:", gray);
1299
+ const boardLabel = colorize("Board:", gray);
1300
+ return `${handLabel} ${handStr} | ${boardLabel} ${boardStr} \u2192 ${this.handResult?.text}`;
1107
1301
  }
1108
1302
  };
1109
1303
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-scope",
3
- "version": "0.4.0",
3
+ "version": "0.4.2",
4
4
  "description": "Claude Code plugin for session status and analytics",
5
5
  "license": "MIT",
6
6
  "type": "module",