diff --git a/dist/rarity.d.mts.map b/dist/rarity.d.mts.map index 15a732c..70c8fce 100644 --- a/dist/rarity.d.mts.map +++ b/dist/rarity.d.mts.map @@ -1 +1 @@ -{"version":3,"file":"rarity.d.mts","names":[],"sources":["../rarity.ts"],"mappings":";UAEiB,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;EACf,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;EACA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;AAAA;AAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAiBc,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAoB,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;AAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAYpB,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAoC,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;AAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAapC,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAoB,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;AAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAKpB,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAkB,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;AAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAalB,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAsB,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;AAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAItB,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAsB,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;AAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAItB,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAsB,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;AAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAItB,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CACd,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;AAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAKc,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CACd,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;AAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAoBc,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CACd,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CACA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA"} \ No newline at end of file +{"version":3,"file":"rarity.d.mts","names":[],"sources":["../rarity.ts"],"mappings":";UAEiB,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;EACf,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;EACA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;AAAA;AAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAiBc,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAoB,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;AAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAYpB,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAoC,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;AAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAapC,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAoB,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;AAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAKpB,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAkB,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;AAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAalB,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAsB,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;AAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAItB,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAsB,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;AAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAItB,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAsB,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;AAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAItB,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CACd,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;AAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAKc,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CACd,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;AAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAWc,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CACd,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CACA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA"} \ No newline at end of file diff --git a/dist/rarity.mjs b/dist/rarity.mjs index 7f4a6ee..8a823d6 100644 --- a/dist/rarity.mjs +++ b/dist/rarity.mjs @@ -1,2 +1,2 @@ -function e(e){return Math.max(0,40-e+1)}function t(t,n){return t*(e(n)/16**n)}function n(e){let t=0,n=10;for(;n<=e;)t+=1,n*=10;return t}function r(e){if(e<10)return 0;let t=e.toString().length,n=(t-2)*9,r=10**(t-1),i=Math.floor(e/r);return n+Math.min(i,9)}function i(e){return[512,1024,2048,4096,8192,16384,32768,65536].filter(t=>t<=e).length}function a(e){let t=0;for(let n=3;n<=e.toString().length;n+=1)Number.parseInt(`7`.repeat(n),10)<=e&&(t+=1);return t}function o(e){return t(e,3)}function s(e){return t(e,3)}function c(e){return t(e,3)}function l(t){return t*(e(5)/16**4)}function u(t){return t*[`f00d`,`feed`,`cafe`,`c0ffee`,`deadbeef`,`defecated`,`0ffice`,`badcable`].reduce((t,n)=>t+e(n.length)/16**n.length,0)}function d(e,t){return t===void 0?!0:e<=t}export{a as expectedAllSevens,c as expectedCommitHits123,s as expectedCommitHits666,o as expectedCommitHits777,u as expectedCommitHitsHexspeak,l as expectedCommitHitsSameNumbers,n as expectedPowersOfTen,i as expectedPowersOfTwo,r as expectedSingleNonzeroDigitPrNumbers,d as isRareEnough}; +function e(e){return Math.max(0,40-e+1)}function t(t,n){return t*(e(n)/16**n)}function n(e){let t=0,n=10;for(;n<=e;)t+=1,n*=10;return t}function r(e){if(e<10)return 0;let t=e.toString().length,n=(t-2)*9,r=10**(t-1),i=Math.floor(e/r);return n+Math.min(i,9)}function i(e){return[512,1024,2048,4096,8192,16384,32768,65536].filter(t=>t<=e).length}function a(e){let t=0;for(let n=3;n<=e.toString().length;n+=1)Number.parseInt(`7`.repeat(n),10)<=e&&(t+=1);return t}function o(e){return t(e,3)}function s(e){return t(e,3)}function c(e){return t(e,3)}function l(t){return t*(e(5)/16**4)}function u(t){return t*[`f00d`,`feed`,`cafe`,`c0ffee`,`deadbeef`].reduce((t,n)=>t+e(n.length)/16**n.length,0)}function d(e,t){return t===void 0?!0:e<=t}export{a as expectedAllSevens,c as expectedCommitHits123,s as expectedCommitHits666,o as expectedCommitHits777,u as expectedCommitHitsHexspeak,l as expectedCommitHitsSameNumbers,n as expectedPowersOfTen,i as expectedPowersOfTwo,r as expectedSingleNonzeroDigitPrNumbers,d as isRareEnough}; //# sourceMappingURL=rarity.mjs.map \ No newline at end of file diff --git a/dist/rarity.mjs.map b/dist/rarity.mjs.map index b0165ef..27578b7 100644 --- a/dist/rarity.mjs.map +++ b/dist/rarity.mjs.map @@ -1 +1 @@ -{"version":3,"file":"rarity.mjs","names":[],"sources":["../src/rarity.ts"],"sourcesContent":["const SHA_LENGTH = 40\n\nexport interface RarityContext {\n prNum: number\n repositoryCommitCount: number\n}\n\nfunction slidingWindows(length: number): number {\n return Math.max(0, SHA_LENGTH - length + 1)\n}\n\nfunction expectedOccurrencesFromSubstringProbability(\n repositoryCommitCount: number,\n substringLength: number\n): number {\n return (\n repositoryCommitCount *\n (slidingWindows(substringLength) / 16 ** substringLength)\n )\n}\n\nexport function expectedPowersOfTen(prNum: number): number {\n let count = 0\n let current = 10\n\n while (current <= prNum) {\n count += 1\n current *= 10\n }\n\n return count\n}\n\nexport function expectedSingleNonzeroDigitPrNumbers(prNum: number): number {\n if (prNum < 10) {\n return 0\n }\n\n const digits = prNum.toString().length\n const shorterDigitMatches = (digits - 2) * 9\n const currentDigitBase = 10 ** (digits - 1)\n const currentLeadingDigit = Math.floor(prNum / currentDigitBase)\n\n return shorterDigitMatches + Math.min(currentLeadingDigit, 9)\n}\n\nexport function expectedPowersOfTwo(prNum: number): number {\n const values = [512, 1024, 2048, 4096, 8192, 16384, 32768, 65536]\n return values.filter((value) => value <= prNum).length\n}\n\nexport function expectedAllSevens(prNum: number): number {\n let count = 0\n\n for (let digits = 3; digits <= prNum.toString().length; digits += 1) {\n const value = Number.parseInt('7'.repeat(digits), 10)\n if (value <= prNum) {\n count += 1\n }\n }\n\n return count\n}\n\nexport function expectedCommitHits777(repositoryCommitCount: number): number {\n return expectedOccurrencesFromSubstringProbability(repositoryCommitCount, 3)\n}\n\nexport function expectedCommitHits666(repositoryCommitCount: number): number {\n return expectedOccurrencesFromSubstringProbability(repositoryCommitCount, 3)\n}\n\nexport function expectedCommitHits123(repositoryCommitCount: number): number {\n return expectedOccurrencesFromSubstringProbability(repositoryCommitCount, 3)\n}\n\nexport function expectedCommitHitsSameNumbers(\n repositoryCommitCount: number\n): number {\n return repositoryCommitCount * (slidingWindows(5) / 16 ** 4)\n}\n\nexport function expectedCommitHitsHexspeak(\n repositoryCommitCount: number\n): number {\n const patterns = [\n 'f00d',\n 'feed',\n 'cafe',\n 'c0ffee',\n 'deadbeef',\n 'defecated',\n '0ffice',\n 'badcable',\n ]\n\n const probability = patterns.reduce((sum, pattern) => {\n return sum + slidingWindows(pattern.length) / 16 ** pattern.length\n }, 0)\n\n return repositoryCommitCount * probability\n}\n\nexport function isRareEnough(\n expectedOccurrences: number,\n maxExpectedOccurrences?: number\n): boolean {\n if (maxExpectedOccurrences === undefined) {\n return true\n }\n\n return expectedOccurrences <= maxExpectedOccurrences\n}\n"],"mappings":"AAOA,SAAS,EAAe,EAAwB,CAC9C,OAAO,KAAK,IAAI,EAAG,GAAa,EAAS,EAAE,CAG7C,SAAS,EACP,EACA,EACQ,CACR,OACE,GACC,EAAe,EAAgB,CAAG,IAAM,GAI7C,SAAgB,EAAoB,EAAuB,CACzD,IAAI,EAAQ,EACR,EAAU,GAEd,KAAO,GAAW,GAChB,GAAS,EACT,GAAW,GAGb,OAAO,EAGT,SAAgB,EAAoC,EAAuB,CACzE,GAAI,EAAQ,GACV,MAAO,GAGT,IAAM,EAAS,EAAM,UAAU,CAAC,OAC1B,GAAuB,EAAS,GAAK,EACrC,EAAmB,KAAO,EAAS,GACnC,EAAsB,KAAK,MAAM,EAAQ,EAAiB,CAEhE,OAAO,EAAsB,KAAK,IAAI,EAAqB,EAAE,CAG/D,SAAgB,EAAoB,EAAuB,CAEzD,MADe,CAAC,IAAK,KAAM,KAAM,KAAM,KAAM,MAAO,MAAO,MAAM,CACnD,OAAQ,GAAU,GAAS,EAAM,CAAC,OAGlD,SAAgB,EAAkB,EAAuB,CACvD,IAAI,EAAQ,EAEZ,IAAK,IAAI,EAAS,EAAG,GAAU,EAAM,UAAU,CAAC,OAAQ,GAAU,EAClD,OAAO,SAAS,IAAI,OAAO,EAAO,CAAE,GAAG,EACxC,IACX,GAAS,GAIb,OAAO,EAGT,SAAgB,EAAsB,EAAuC,CAC3E,OAAO,EAA4C,EAAuB,EAAE,CAG9E,SAAgB,EAAsB,EAAuC,CAC3E,OAAO,EAA4C,EAAuB,EAAE,CAG9E,SAAgB,EAAsB,EAAuC,CAC3E,OAAO,EAA4C,EAAuB,EAAE,CAG9E,SAAgB,EACd,EACQ,CACR,OAAO,GAAyB,EAAe,EAAE,CAAG,IAAM,GAG5D,SAAgB,EACd,EACQ,CAgBR,OAAO,EAfU,CACf,OACA,OACA,OACA,SACA,WACA,YACA,SACA,WACD,CAE4B,QAAQ,EAAK,IACjC,EAAM,EAAe,EAAQ,OAAO,CAAG,IAAM,EAAQ,OAC3D,EAAE,CAKP,SAAgB,EACd,EACA,EACS,CAKT,OAJI,IAA2B,IAAA,GACtB,GAGF,GAAuB"} \ No newline at end of file +{"version":3,"file":"rarity.mjs","names":[],"sources":["../src/rarity.ts"],"sourcesContent":["const SHA_LENGTH = 40\n\nexport interface RarityContext {\n prNum: number\n repositoryCommitCount: number\n}\n\nfunction slidingWindows(length: number): number {\n return Math.max(0, SHA_LENGTH - length + 1)\n}\n\nfunction expectedOccurrencesFromSubstringProbability(\n repositoryCommitCount: number,\n substringLength: number\n): number {\n return (\n repositoryCommitCount *\n (slidingWindows(substringLength) / 16 ** substringLength)\n )\n}\n\nexport function expectedPowersOfTen(prNum: number): number {\n let count = 0\n let current = 10\n\n while (current <= prNum) {\n count += 1\n current *= 10\n }\n\n return count\n}\n\nexport function expectedSingleNonzeroDigitPrNumbers(prNum: number): number {\n if (prNum < 10) {\n return 0\n }\n\n const digits = prNum.toString().length\n const shorterDigitMatches = (digits - 2) * 9\n const currentDigitBase = 10 ** (digits - 1)\n const currentLeadingDigit = Math.floor(prNum / currentDigitBase)\n\n return shorterDigitMatches + Math.min(currentLeadingDigit, 9)\n}\n\nexport function expectedPowersOfTwo(prNum: number): number {\n const values = [512, 1024, 2048, 4096, 8192, 16384, 32768, 65536]\n return values.filter((value) => value <= prNum).length\n}\n\nexport function expectedAllSevens(prNum: number): number {\n let count = 0\n\n for (let digits = 3; digits <= prNum.toString().length; digits += 1) {\n const value = Number.parseInt('7'.repeat(digits), 10)\n if (value <= prNum) {\n count += 1\n }\n }\n\n return count\n}\n\nexport function expectedCommitHits777(repositoryCommitCount: number): number {\n return expectedOccurrencesFromSubstringProbability(repositoryCommitCount, 3)\n}\n\nexport function expectedCommitHits666(repositoryCommitCount: number): number {\n return expectedOccurrencesFromSubstringProbability(repositoryCommitCount, 3)\n}\n\nexport function expectedCommitHits123(repositoryCommitCount: number): number {\n return expectedOccurrencesFromSubstringProbability(repositoryCommitCount, 3)\n}\n\nexport function expectedCommitHitsSameNumbers(\n repositoryCommitCount: number\n): number {\n return repositoryCommitCount * (slidingWindows(5) / 16 ** 4)\n}\n\nexport function expectedCommitHitsHexspeak(\n repositoryCommitCount: number\n): number {\n const patterns = ['f00d', 'feed', 'cafe', 'c0ffee', 'deadbeef']\n\n const probability = patterns.reduce((sum, pattern) => {\n return sum + slidingWindows(pattern.length) / 16 ** pattern.length\n }, 0)\n\n return repositoryCommitCount * probability\n}\n\nexport function isRareEnough(\n expectedOccurrences: number,\n maxExpectedOccurrences?: number\n): boolean {\n if (maxExpectedOccurrences === undefined) {\n return true\n }\n\n return expectedOccurrences <= maxExpectedOccurrences\n}\n"],"mappings":"AAOA,SAAS,EAAe,EAAwB,CAC9C,OAAO,KAAK,IAAI,EAAG,GAAa,EAAS,EAAE,CAG7C,SAAS,EACP,EACA,EACQ,CACR,OACE,GACC,EAAe,EAAgB,CAAG,IAAM,GAI7C,SAAgB,EAAoB,EAAuB,CACzD,IAAI,EAAQ,EACR,EAAU,GAEd,KAAO,GAAW,GAChB,GAAS,EACT,GAAW,GAGb,OAAO,EAGT,SAAgB,EAAoC,EAAuB,CACzE,GAAI,EAAQ,GACV,MAAO,GAGT,IAAM,EAAS,EAAM,UAAU,CAAC,OAC1B,GAAuB,EAAS,GAAK,EACrC,EAAmB,KAAO,EAAS,GACnC,EAAsB,KAAK,MAAM,EAAQ,EAAiB,CAEhE,OAAO,EAAsB,KAAK,IAAI,EAAqB,EAAE,CAG/D,SAAgB,EAAoB,EAAuB,CAEzD,MADe,CAAC,IAAK,KAAM,KAAM,KAAM,KAAM,MAAO,MAAO,MAAM,CACnD,OAAQ,GAAU,GAAS,EAAM,CAAC,OAGlD,SAAgB,EAAkB,EAAuB,CACvD,IAAI,EAAQ,EAEZ,IAAK,IAAI,EAAS,EAAG,GAAU,EAAM,UAAU,CAAC,OAAQ,GAAU,EAClD,OAAO,SAAS,IAAI,OAAO,EAAO,CAAE,GAAG,EACxC,IACX,GAAS,GAIb,OAAO,EAGT,SAAgB,EAAsB,EAAuC,CAC3E,OAAO,EAA4C,EAAuB,EAAE,CAG9E,SAAgB,EAAsB,EAAuC,CAC3E,OAAO,EAA4C,EAAuB,EAAE,CAG9E,SAAgB,EAAsB,EAAuC,CAC3E,OAAO,EAA4C,EAAuB,EAAE,CAG9E,SAAgB,EACd,EACQ,CACR,OAAO,GAAyB,EAAe,EAAE,CAAG,IAAM,GAG5D,SAAgB,EACd,EACQ,CAOR,OAAO,EANU,CAAC,OAAQ,OAAQ,OAAQ,SAAU,WAAW,CAElC,QAAQ,EAAK,IACjC,EAAM,EAAe,EAAQ,OAAO,CAAG,IAAM,EAAQ,OAC3D,EAAE,CAKP,SAAgB,EACd,EACA,EACS,CAKT,OAJI,IAA2B,IAAA,GACtB,GAGF,GAAuB"} \ No newline at end of file diff --git a/dist/rules.mjs b/dist/rules.mjs index 4e7af62..475c5ca 100644 --- a/dist/rules.mjs +++ b/dist/rules.mjs @@ -1,2 +1,2 @@ -import{expectedAllSevens as e,expectedCommitHits123 as t,expectedCommitHits666 as n,expectedCommitHits777 as r,expectedCommitHitsHexspeak as i,expectedCommitHitsSameNumbers as a,expectedPowersOfTwo as o,expectedSingleNonzeroDigitPrNumbers as s}from"./rarity.mjs";import"./ajv-QtvvyOqs.mjs";import{validateRules as c}from"./validate.mjs";function l(e){let t;try{t=JSON.parse(e)}catch{throw Error(`Invalid JSON`)}if(c(t))return t;throw Error(`Invalid rules: ${JSON.stringify(c.errors)}`)}function u(e){let t=l(e),n=[];for(let e of t)try{n.push({kind:e.kind,rule:new RegExp(e.rule),message:e.message})}catch{throw Error(`Invalid rule: ${e.rule}`)}return n}const d={pr_reaches_contain_only_one_nonzero_digit:{id:`pr_reaches_contain_only_one_nonzero_digit`,kind:`pr`,rule:/(?:^[1-9]0+$)/,message:`Now pull request issue number reaches **{{prNum}}**. It's time to celebrate!`,expectedOccurrences:({prNum:e})=>s(e)},pr_reaches_power_of_2:{id:`pr_reaches_power_of_2`,kind:`pr`,rule:/(?:^(512|1024|2048|4096|8192|16384|32768|65536)$)/,message:`Now pull request issue number reaches **{{prNum}}** (power of 2). It's time to celebrate!`,expectedOccurrences:({prNum:e})=>o(e)},pr_reaches_777:{id:`pr_reaches_777`,kind:`pr`,rule:/(?:^7{3,}$)/,message:`Now pull request issue number reaches **{{prNum}}** (777). It's time to celebrate!`,expectedOccurrences:({prNum:t})=>e(t)},commit_hits_777:{id:`commit_hits_777`,kind:`commit`,rule:/(?:7{3,})/,message:"Commit `{{commitId}}` is lucky! It contains **{{matched}}**!.",expectedOccurrences:({repositoryCommitCount:e})=>r(e)},commit_hits_same_numbers:{id:`commit_hits_same_numbers`,kind:`commit`,rule:/(?:([0-9a-f])\1{4,})/,message:"Commit `{{commitId}}` is lucky! It contains **{{matched}}**!.",expectedOccurrences:({repositoryCommitCount:e})=>a(e)},commit_hits_123:{id:`commit_hits_123`,kind:`commit`,rule:/(?:123(?:4(?:5(?:6(?:7(?:8(?:9)?)?)?)?)?)?)/,message:"Commit `{{commitId}}` is lucky! It contains **{{matched}}**!.",expectedOccurrences:({repositoryCommitCount:e})=>t(e)},commit_hits_hexspeak:{id:`commit_hits_hexspeak`,kind:`commit`,rule:/(?:(?:f00d|feed|cafe|c0ffee|deadbeef|defecated|0ffice|badcable))/i,message:"Commit `{{commitId}}` is lucky! It contains **{{matched}}**!.",expectedOccurrences:({repositoryCommitCount:e})=>i(e)},commit_hits_666:{id:`commit_hits_666`,kind:`commit`,rule:/(?:666)/,message:"Commit `{{commitId}}` is unlucky... It contains **{{matched}}**!.",expectedOccurrences:({repositoryCommitCount:e})=>n(e)}};export{d as Rules,u as parseRules}; +import{expectedAllSevens as e,expectedCommitHits123 as t,expectedCommitHits666 as n,expectedCommitHits777 as r,expectedCommitHitsHexspeak as i,expectedCommitHitsSameNumbers as a,expectedPowersOfTwo as o,expectedSingleNonzeroDigitPrNumbers as s}from"./rarity.mjs";import"./ajv-QtvvyOqs.mjs";import{validateRules as c}from"./validate.mjs";function l(e){let t;try{t=JSON.parse(e)}catch{throw Error(`Invalid JSON`)}if(c(t))return t;throw Error(`Invalid rules: ${JSON.stringify(c.errors)}`)}function u(e){let t=l(e),n=[];for(let e of t)try{n.push({kind:e.kind,rule:new RegExp(e.rule),message:e.message})}catch{throw Error(`Invalid rule: ${e.rule}`)}return n}const d={pr_reaches_contain_only_one_nonzero_digit:{id:`pr_reaches_contain_only_one_nonzero_digit`,kind:`pr`,rule:/(?:^[1-9]0+$)/,message:`Now pull request issue number reaches **{{prNum}}**. It's time to celebrate!`,expectedOccurrences:({prNum:e})=>s(e)},pr_reaches_power_of_2:{id:`pr_reaches_power_of_2`,kind:`pr`,rule:/(?:^(512|1024|2048|4096|8192|16384|32768|65536)$)/,message:`Now pull request issue number reaches **{{prNum}}** (power of 2). It's time to celebrate!`,expectedOccurrences:({prNum:e})=>o(e)},pr_reaches_777:{id:`pr_reaches_777`,kind:`pr`,rule:/(?:^7{3,}$)/,message:`Now pull request issue number reaches **{{prNum}}** (777). It's time to celebrate!`,expectedOccurrences:({prNum:t})=>e(t)},commit_hits_777:{id:`commit_hits_777`,kind:`commit`,rule:/(?:7{3,})/,message:"Commit `{{commitId}}` is lucky! It contains **{{matched}}**!.",expectedOccurrences:({repositoryCommitCount:e})=>r(e)},commit_hits_same_numbers:{id:`commit_hits_same_numbers`,kind:`commit`,rule:/(?:([0-9a-f])\1{4,})/,message:"Commit `{{commitId}}` is lucky! It contains **{{matched}}**!.",expectedOccurrences:({repositoryCommitCount:e})=>a(e)},commit_hits_123:{id:`commit_hits_123`,kind:`commit`,rule:/(?:123(?:4(?:5(?:6(?:7(?:8(?:9)?)?)?)?)?)?)/,message:"Commit `{{commitId}}` is lucky! It contains **{{matched}}**!.",expectedOccurrences:({repositoryCommitCount:e})=>t(e)},commit_hits_hexspeak:{id:`commit_hits_hexspeak`,kind:`commit`,rule:/(?:(?:f00d|feed|cafe|c0ffee|deadbeef))/,message:"Commit `{{commitId}}` is lucky! It contains **{{matched}}**!.",expectedOccurrences:({repositoryCommitCount:e})=>i(e)},commit_hits_666:{id:`commit_hits_666`,kind:`commit`,rule:/(?:666)/,message:"Commit `{{commitId}}` is unlucky... It contains **{{matched}}**!.",expectedOccurrences:({repositoryCommitCount:e})=>n(e)}};export{d as Rules,u as parseRules}; //# sourceMappingURL=rules.mjs.map \ No newline at end of file diff --git a/dist/rules.mjs.map b/dist/rules.mjs.map index c5ca1ba..9a95d6c 100644 --- a/dist/rules.mjs.map +++ b/dist/rules.mjs.map @@ -1 +1 @@ -{"version":3,"file":"rules.mjs","names":[],"sources":["../src/rules.ts"],"sourcesContent":["import type {\n MessageForRuleSet,\n NamedMessageForRuleSet,\n RuleStringPattern,\n RuleStringPatterns,\n} from './interfaces'\nimport {\n expectedAllSevens,\n expectedCommitHits123,\n expectedCommitHits666,\n expectedCommitHits777,\n expectedCommitHitsHexspeak,\n expectedCommitHitsSameNumbers,\n expectedPowersOfTwo,\n expectedSingleNonzeroDigitPrNumbers,\n} from './rarity'\nimport { validateRules } from './validate'\n\nexport type { RuleStringPattern }\n\n/**\n * Parse the rule pattern from JSON string\n * this function does not validate the RegExp pattern\n * @param json {string} the JSON string\n * @returns {RuleStringPatterns} the rule pattern\n * @throws {Error} if the JSON is invalid\n * @throws {Error} if the rule pattern is invalid\n */\nfunction parseRulePatternFromJson(json: string): RuleStringPatterns {\n let parsed: unknown\n try {\n parsed = JSON.parse(json)\n } catch (_e: unknown) {\n throw new Error('Invalid JSON')\n }\n const validated = validateRules(parsed)\n if (validated) {\n return parsed as RuleStringPatterns\n }\n throw new Error(`Invalid rules: ${JSON.stringify(validateRules.errors)}`)\n}\n\n/**\n * Parse the rule pattern from JSON string and convert it to rule set\n * @param json {string} the JSON string\n * @returns {MessageForRuleSet} the rule set\n * @throws {Error} if the rule is invalid\n * @throws {Error} if the JSON is invalid\n * @throws {Error} if the rule set is invalid\n */\nexport function parseRules(json: string): MessageForRuleSet {\n const parsed = parseRulePatternFromJson(json)\n const rules: MessageForRuleSet = []\n for (const rule of parsed) {\n try {\n rules.push({\n kind: rule.kind,\n rule: new RegExp(rule.rule),\n message: rule.message,\n })\n } catch (_e: unknown) {\n throw new Error(`Invalid rule: ${rule.rule}`)\n }\n }\n return rules\n}\n\nexport const Rules: NamedMessageForRuleSet = {\n pr_reaches_contain_only_one_nonzero_digit: {\n id: 'pr_reaches_contain_only_one_nonzero_digit',\n kind: 'pr',\n rule: /(?:^[1-9]0+$)/,\n message: `Now pull request issue number reaches **{{prNum}}**. It's time to celebrate!`,\n expectedOccurrences: ({ prNum }) =>\n expectedSingleNonzeroDigitPrNumbers(prNum),\n },\n pr_reaches_power_of_2: {\n id: 'pr_reaches_power_of_2',\n kind: 'pr',\n rule: /(?:^(512|1024|2048|4096|8192|16384|32768|65536)$)/,\n message: `Now pull request issue number reaches **{{prNum}}** (power of 2). It's time to celebrate!`,\n expectedOccurrences: ({ prNum }) => expectedPowersOfTwo(prNum),\n },\n pr_reaches_777: {\n id: 'pr_reaches_777',\n kind: 'pr',\n rule: /(?:^7{3,}$)/,\n message: `Now pull request issue number reaches **{{prNum}}** (777). It's time to celebrate!`,\n expectedOccurrences: ({ prNum }) => expectedAllSevens(prNum),\n },\n commit_hits_777: {\n id: 'commit_hits_777',\n kind: 'commit',\n rule: /(?:7{3,})/,\n message: 'Commit `{{commitId}}` is lucky! It contains **{{matched}}**!.',\n expectedOccurrences: ({ repositoryCommitCount }) =>\n expectedCommitHits777(repositoryCommitCount),\n },\n commit_hits_same_numbers: {\n id: 'commit_hits_same_numbers',\n kind: 'commit',\n rule: /(?:([0-9a-f])\\1{4,})/,\n message: 'Commit `{{commitId}}` is lucky! It contains **{{matched}}**!.',\n expectedOccurrences: ({ repositoryCommitCount }) =>\n expectedCommitHitsSameNumbers(repositoryCommitCount),\n },\n commit_hits_123: {\n id: 'commit_hits_123',\n kind: 'commit',\n rule: /(?:123(?:4(?:5(?:6(?:7(?:8(?:9)?)?)?)?)?)?)/,\n message: 'Commit `{{commitId}}` is lucky! It contains **{{matched}}**!.',\n expectedOccurrences: ({ repositoryCommitCount }) =>\n expectedCommitHits123(repositoryCommitCount),\n },\n commit_hits_hexspeak: {\n id: 'commit_hits_hexspeak',\n kind: 'commit',\n rule: /(?:(?:f00d|feed|cafe|c0ffee|deadbeef|defecated|0ffice|badcable))/i,\n message: 'Commit `{{commitId}}` is lucky! It contains **{{matched}}**!.',\n expectedOccurrences: ({ repositoryCommitCount }) =>\n expectedCommitHitsHexspeak(repositoryCommitCount),\n },\n commit_hits_666: {\n id: 'commit_hits_666',\n kind: 'commit',\n rule: /(?:666)/,\n message:\n 'Commit `{{commitId}}` is unlucky... It contains **{{matched}}**!.',\n expectedOccurrences: ({ repositoryCommitCount }) =>\n expectedCommitHits666(repositoryCommitCount),\n },\n} as const\n\nexport type RulesKey = keyof typeof Rules\n"],"mappings":"iVA4BA,SAAS,EAAyB,EAAkC,CAClE,IAAI,EACJ,GAAI,CACF,EAAS,KAAK,MAAM,EAAK,MACL,CACpB,MAAU,MAAM,eAAe,CAGjC,GADkB,EAAc,EAAO,CAErC,OAAO,EAET,MAAU,MAAM,kBAAkB,KAAK,UAAU,EAAc,OAAO,GAAG,CAW3E,SAAgB,EAAW,EAAiC,CAC1D,IAAM,EAAS,EAAyB,EAAK,CACvC,EAA2B,EAAE,CACnC,IAAK,IAAM,KAAQ,EACjB,GAAI,CACF,EAAM,KAAK,CACT,KAAM,EAAK,KACX,KAAM,IAAI,OAAO,EAAK,KAAK,CAC3B,QAAS,EAAK,QACf,CAAC,MACkB,CACpB,MAAU,MAAM,iBAAiB,EAAK,OAAO,CAGjD,OAAO,EAGT,MAAa,EAAgC,CAC3C,0CAA2C,CACzC,GAAI,4CACJ,KAAM,KACN,KAAM,gBACN,QAAS,+EACT,qBAAsB,CAAE,WACtB,EAAoC,EAAA,CACvC,CACD,sBAAuB,CACrB,GAAI,wBACJ,KAAM,KACN,KAAM,oDACN,QAAS,4FACT,qBAAsB,CAAE,WAAY,EAAoB,EAAA,CACzD,CACD,eAAgB,CACd,GAAI,iBACJ,KAAM,KACN,KAAM,cACN,QAAS,qFACT,qBAAsB,CAAE,WAAY,EAAkB,EAAA,CACvD,CACD,gBAAiB,CACf,GAAI,kBACJ,KAAM,SACN,KAAM,YACN,QAAS,gEACT,qBAAsB,CAAE,2BACtB,EAAsB,EAAA,CACzB,CACD,yBAA0B,CACxB,GAAI,2BACJ,KAAM,SACN,KAAM,uBACN,QAAS,gEACT,qBAAsB,CAAE,2BACtB,EAA8B,EAAA,CACjC,CACD,gBAAiB,CACf,GAAI,kBACJ,KAAM,SACN,KAAM,8CACN,QAAS,gEACT,qBAAsB,CAAE,2BACtB,EAAsB,EAAA,CACzB,CACD,qBAAsB,CACpB,GAAI,uBACJ,KAAM,SACN,KAAM,oEACN,QAAS,gEACT,qBAAsB,CAAE,2BACtB,EAA2B,EAAA,CAC9B,CACD,gBAAiB,CACf,GAAI,kBACJ,KAAM,SACN,KAAM,UACN,QACE,oEACF,qBAAsB,CAAE,2BACtB,EAAsB,EAAA,EAE3B"} \ No newline at end of file +{"version":3,"file":"rules.mjs","names":[],"sources":["../src/rules.ts"],"sourcesContent":["import type {\n MessageForRuleSet,\n NamedMessageForRuleSet,\n RuleStringPattern,\n RuleStringPatterns,\n} from './interfaces'\nimport {\n expectedAllSevens,\n expectedCommitHits123,\n expectedCommitHits666,\n expectedCommitHits777,\n expectedCommitHitsHexspeak,\n expectedCommitHitsSameNumbers,\n expectedPowersOfTwo,\n expectedSingleNonzeroDigitPrNumbers,\n} from './rarity'\nimport { validateRules } from './validate'\n\nexport type { RuleStringPattern }\n\n/**\n * Parse the rule pattern from JSON string\n * this function does not validate the RegExp pattern\n * @param json {string} the JSON string\n * @returns {RuleStringPatterns} the rule pattern\n * @throws {Error} if the JSON is invalid\n * @throws {Error} if the rule pattern is invalid\n */\nfunction parseRulePatternFromJson(json: string): RuleStringPatterns {\n let parsed: unknown\n try {\n parsed = JSON.parse(json)\n } catch (_e: unknown) {\n throw new Error('Invalid JSON')\n }\n const validated = validateRules(parsed)\n if (validated) {\n return parsed as RuleStringPatterns\n }\n throw new Error(`Invalid rules: ${JSON.stringify(validateRules.errors)}`)\n}\n\n/**\n * Parse the rule pattern from JSON string and convert it to rule set\n * @param json {string} the JSON string\n * @returns {MessageForRuleSet} the rule set\n * @throws {Error} if the rule is invalid\n * @throws {Error} if the JSON is invalid\n * @throws {Error} if the rule set is invalid\n */\nexport function parseRules(json: string): MessageForRuleSet {\n const parsed = parseRulePatternFromJson(json)\n const rules: MessageForRuleSet = []\n for (const rule of parsed) {\n try {\n rules.push({\n kind: rule.kind,\n rule: new RegExp(rule.rule),\n message: rule.message,\n })\n } catch (_e: unknown) {\n throw new Error(`Invalid rule: ${rule.rule}`)\n }\n }\n return rules\n}\n\nexport const Rules: NamedMessageForRuleSet = {\n pr_reaches_contain_only_one_nonzero_digit: {\n id: 'pr_reaches_contain_only_one_nonzero_digit',\n kind: 'pr',\n rule: /(?:^[1-9]0+$)/,\n message: `Now pull request issue number reaches **{{prNum}}**. It's time to celebrate!`,\n expectedOccurrences: ({ prNum }) =>\n expectedSingleNonzeroDigitPrNumbers(prNum),\n },\n pr_reaches_power_of_2: {\n id: 'pr_reaches_power_of_2',\n kind: 'pr',\n rule: /(?:^(512|1024|2048|4096|8192|16384|32768|65536)$)/,\n message: `Now pull request issue number reaches **{{prNum}}** (power of 2). It's time to celebrate!`,\n expectedOccurrences: ({ prNum }) => expectedPowersOfTwo(prNum),\n },\n pr_reaches_777: {\n id: 'pr_reaches_777',\n kind: 'pr',\n rule: /(?:^7{3,}$)/,\n message: `Now pull request issue number reaches **{{prNum}}** (777). It's time to celebrate!`,\n expectedOccurrences: ({ prNum }) => expectedAllSevens(prNum),\n },\n commit_hits_777: {\n id: 'commit_hits_777',\n kind: 'commit',\n rule: /(?:7{3,})/,\n message: 'Commit `{{commitId}}` is lucky! It contains **{{matched}}**!.',\n expectedOccurrences: ({ repositoryCommitCount }) =>\n expectedCommitHits777(repositoryCommitCount),\n },\n commit_hits_same_numbers: {\n id: 'commit_hits_same_numbers',\n kind: 'commit',\n rule: /(?:([0-9a-f])\\1{4,})/,\n message: 'Commit `{{commitId}}` is lucky! It contains **{{matched}}**!.',\n expectedOccurrences: ({ repositoryCommitCount }) =>\n expectedCommitHitsSameNumbers(repositoryCommitCount),\n },\n commit_hits_123: {\n id: 'commit_hits_123',\n kind: 'commit',\n rule: /(?:123(?:4(?:5(?:6(?:7(?:8(?:9)?)?)?)?)?)?)/,\n message: 'Commit `{{commitId}}` is lucky! It contains **{{matched}}**!.',\n expectedOccurrences: ({ repositoryCommitCount }) =>\n expectedCommitHits123(repositoryCommitCount),\n },\n commit_hits_hexspeak: {\n id: 'commit_hits_hexspeak',\n kind: 'commit',\n rule: /(?:(?:f00d|feed|cafe|c0ffee|deadbeef))/,\n message: 'Commit `{{commitId}}` is lucky! It contains **{{matched}}**!.',\n expectedOccurrences: ({ repositoryCommitCount }) =>\n expectedCommitHitsHexspeak(repositoryCommitCount),\n },\n commit_hits_666: {\n id: 'commit_hits_666',\n kind: 'commit',\n rule: /(?:666)/,\n message:\n 'Commit `{{commitId}}` is unlucky... It contains **{{matched}}**!.',\n expectedOccurrences: ({ repositoryCommitCount }) =>\n expectedCommitHits666(repositoryCommitCount),\n },\n} as const\n\nexport type RulesKey = keyof typeof Rules\n"],"mappings":"iVA4BA,SAAS,EAAyB,EAAkC,CAClE,IAAI,EACJ,GAAI,CACF,EAAS,KAAK,MAAM,EAAK,MACL,CACpB,MAAU,MAAM,eAAe,CAGjC,GADkB,EAAc,EAAO,CAErC,OAAO,EAET,MAAU,MAAM,kBAAkB,KAAK,UAAU,EAAc,OAAO,GAAG,CAW3E,SAAgB,EAAW,EAAiC,CAC1D,IAAM,EAAS,EAAyB,EAAK,CACvC,EAA2B,EAAE,CACnC,IAAK,IAAM,KAAQ,EACjB,GAAI,CACF,EAAM,KAAK,CACT,KAAM,EAAK,KACX,KAAM,IAAI,OAAO,EAAK,KAAK,CAC3B,QAAS,EAAK,QACf,CAAC,MACkB,CACpB,MAAU,MAAM,iBAAiB,EAAK,OAAO,CAGjD,OAAO,EAGT,MAAa,EAAgC,CAC3C,0CAA2C,CACzC,GAAI,4CACJ,KAAM,KACN,KAAM,gBACN,QAAS,+EACT,qBAAsB,CAAE,WACtB,EAAoC,EAAA,CACvC,CACD,sBAAuB,CACrB,GAAI,wBACJ,KAAM,KACN,KAAM,oDACN,QAAS,4FACT,qBAAsB,CAAE,WAAY,EAAoB,EAAA,CACzD,CACD,eAAgB,CACd,GAAI,iBACJ,KAAM,KACN,KAAM,cACN,QAAS,qFACT,qBAAsB,CAAE,WAAY,EAAkB,EAAA,CACvD,CACD,gBAAiB,CACf,GAAI,kBACJ,KAAM,SACN,KAAM,YACN,QAAS,gEACT,qBAAsB,CAAE,2BACtB,EAAsB,EAAA,CACzB,CACD,yBAA0B,CACxB,GAAI,2BACJ,KAAM,SACN,KAAM,uBACN,QAAS,gEACT,qBAAsB,CAAE,2BACtB,EAA8B,EAAA,CACjC,CACD,gBAAiB,CACf,GAAI,kBACJ,KAAM,SACN,KAAM,8CACN,QAAS,gEACT,qBAAsB,CAAE,2BACtB,EAAsB,EAAA,CACzB,CACD,qBAAsB,CACpB,GAAI,uBACJ,KAAM,SACN,KAAM,yCACN,QAAS,gEACT,qBAAsB,CAAE,2BACtB,EAA2B,EAAA,CAC9B,CACD,gBAAiB,CACf,GAAI,kBACJ,KAAM,SACN,KAAM,UACN,QACE,oEACF,qBAAsB,CAAE,2BACtB,EAAsB,EAAA,EAE3B"} \ No newline at end of file diff --git a/src/rarity.ts b/src/rarity.ts index 3ae9748..4a6901f 100644 --- a/src/rarity.ts +++ b/src/rarity.ts @@ -83,16 +83,7 @@ export function expectedCommitHitsSameNumbers( export function expectedCommitHitsHexspeak( repositoryCommitCount: number ): number { - const patterns = [ - 'f00d', - 'feed', - 'cafe', - 'c0ffee', - 'deadbeef', - 'defecated', - '0ffice', - 'badcable', - ] + const patterns = ['f00d', 'feed', 'cafe', 'c0ffee', 'deadbeef'] const probability = patterns.reduce((sum, pattern) => { return sum + slidingWindows(pattern.length) / 16 ** pattern.length diff --git a/src/rules.spec.ts b/src/rules.spec.ts index afe2451..b7ec7b2 100644 --- a/src/rules.spec.ts +++ b/src/rules.spec.ts @@ -88,4 +88,18 @@ describe('parseRules', () => { }) ).toBeGreaterThan(0) }) + + it('hexspeak rule only matches patterns composed of valid hex characters', () => { + const rule = Rules.commit_hits_hexspeak.rule + // SHA hashes consist only of [0-9a-f]; these former patterns contain non-hex chars + expect(rule.test('defecated')).toBe(false) // 't' is not hex + expect(rule.test('0ffice')).toBe(false) // 'i' is not hex + expect(rule.test('badcable')).toBe(false) // 'l' is not hex + // Valid hexspeak patterns should still match + expect(rule.test('f00d')).toBe(true) + expect(rule.test('deadbeef')).toBe(true) + expect(rule.test('cafe')).toBe(true) + expect(rule.test('c0ffee')).toBe(true) + expect(rule.test('feed')).toBe(true) + }) }) diff --git a/src/rules.ts b/src/rules.ts index 9026d9e..6ecbd2c 100644 --- a/src/rules.ts +++ b/src/rules.ts @@ -115,7 +115,7 @@ export const Rules: NamedMessageForRuleSet = { commit_hits_hexspeak: { id: 'commit_hits_hexspeak', kind: 'commit', - rule: /(?:(?:f00d|feed|cafe|c0ffee|deadbeef|defecated|0ffice|badcable))/i, + rule: /(?:(?:f00d|feed|cafe|c0ffee|deadbeef))/, message: 'Commit `{{commitId}}` is lucky! It contains **{{matched}}**!.', expectedOccurrences: ({ repositoryCommitCount }) => expectedCommitHitsHexspeak(repositoryCommitCount),