( base: ApiGroup, head: ApiGroup )
| 108 | const groupName = (group: ApiGroup): string => group.path.at(-1) ?? "" |
| 109 | |
| 110 | const groupSimilarity = ( |
| 111 | base: ApiGroup, |
| 112 | head: ApiGroup |
| 113 | ): number => { |
| 114 | const facets = base.entities.flatMap((baseEntity) => { |
| 115 | const headEntity = head.entities.find((candidate) => candidate.bucket === baseEntity.bucket) |
| 116 | return headEntity === undefined ? [] : [{ base: baseEntity, head: headEntity }] |
| 117 | }) |
| 118 | if (facets.length === 0) { |
| 119 | return 0 |
| 120 | } |
| 121 | const sameKind = facets.filter(({ base, head }) => base.declarationKind === head.declarationKind).length / |
| 122 | facets.length |
| 123 | const sameFingerprint = facets.filter(({ base, head }) => base.fingerprint === head.fingerprint).length / |
| 124 | facets.length |
| 125 | const structure = facets.reduce( |
| 126 | (total, { base, head }) => total + setSimilarity(entityFeatures(base), entityFeatures(head)), |
| 127 | 0 |
| 128 | ) / facets.length |
| 129 | const documentation = facets.reduce( |
| 130 | (total, { base, head }) => total + setSimilarity(documentationTokens(base), documentationTokens(head)), |
| 131 | 0 |
| 132 | ) / facets.length |
| 133 | const sameCategory = facets.some(({ base, head }) => |
| 134 | base.documentation.category !== undefined && |
| 135 | base.documentation.category === head.documentation.category |
| 136 | ) |
| 137 | const headModuleName = head.module.split("/").at(-1)?.toLowerCase() |
| 138 | const mentionsHeadModule = headModuleName !== undefined && |
| 139 | facets.some(({ base }) => documentationTokens(base).has(headModuleName)) |
| 140 | const moduleScore = base.module === head.module ? 0.25 : 0 |
| 141 | const packageScore = base.entities[0]!.packageName === head.entities[0]!.packageName ? 0.05 : 0 |
| 142 | return Math.min( |
| 143 | 0.99, |
| 144 | 0.2 * nameSimilarity(groupName(base), groupName(head)) + |
| 145 | (groupName(base) === groupName(head) ? 0.15 : 0) + |
| 146 | moduleScore + |
| 147 | packageScore + |
| 148 | 0.4 * sameFingerprint + |
| 149 | 0.15 * sameKind + |
| 150 | 0.15 * structure + |
| 151 | 0.025 * documentation + |
| 152 | (sameCategory ? 0.05 : 0) + |
| 153 | (mentionsHeadModule ? 0.075 : 0) |
| 154 | ) |
| 155 | } |
| 156 | |
| 157 | const changeId = ( |
| 158 | classification: ChangeClassification, |
no test coverage detected