Commit 299f0be

Anton Medvedev <anton@medv.io>
2023-10-12 10:50:55
Refactor badge merge logic
1 parent aa2018a
Changed files (3)
src/badges.ts
@@ -1,8 +1,6 @@
 import { allBadges } from './all-badges/index.js'
 import { Commit, Data, Pull } from './collect/collect.js'
 import { expectType, linkCommit, linkPull } from './utils.js'
-import { fileURLToPath } from 'url'
-import * as path from 'path'
 
 for (const {
   default: { badges },
@@ -31,49 +29,18 @@ export type Badge = {
   image: string
 }
 
-export function badgeCollection(
-  userBadges: Badge[],
-  presenter: BadgePresenter,
-  compact: boolean,
-) {
-  const indexes = new Map(userBadges.map((x, i) => [x.id, i]))
-  const baseDir = path.basename(path.dirname(fileURLToPath(presenter.url)))
-
+export function badgeCollection(newBadges: Badge[]) {
   return function grant(id: ID, desc: string) {
     const badge: Badge = {
       id,
       tier: 0,
       desc,
       body: '',
-      image: `https://github.com/my-badges/my-badges/blob/master/src/all-badges/${baseDir}/${id}.png?raw=true`,
+      image: '',
     }
-
-    if (compact && presenter.tiers) {
-      let found = false
-      for (const badgeId of presenter.badges as ID[]) {
-        if (indexes.has(badgeId)) {
-          found = true
-          const index = indexes.get(badgeId)!
-          const alreadyExistingBadge = userBadges[index]
-          if (alreadyExistingBadge.tier <= badge.tier) {
-            userBadges[index] = badge
-          }
-          break
-        }
-      }
-      if (!found) {
-        userBadges.push(badge)
-        indexes.set(id, userBadges.length - 1)
-      }
-    } else {
-      if (indexes.has(id)) {
-        userBadges[indexes.get(id)!] = badge
-      } else {
-        userBadges.push(badge)
-        indexes.set(id, userBadges.length - 1)
-      }
+    if (!newBadges.some((x) => x.id === id)) {
+      newBadges.push(badge)
     }
-
     return new Evidence(badge)
   }
 }
src/main.ts
@@ -7,9 +7,11 @@ import { retry } from '@octokit/plugin-retry'
 import { throttling } from '@octokit/plugin-throttling'
 import { collect, Data } from './collect/collect.js'
 import { allBadges } from './all-badges/index.js'
-import { Badge, badgeCollection } from './badges.js'
+import { Badge, badgeCollection, BadgePresenter, ID } from './badges.js'
 import { updateReadme } from './update-readme.js'
 import { updateBadges } from './update-badges.js'
+import path from 'node:path'
+import { fileURLToPath } from 'node:url'
 
 void (async function main() {
   const { env } = process
@@ -100,13 +102,48 @@ void (async function main() {
     }
   }
 
-  for (const { default: presenter } of allBadges) {
-    const grant = badgeCollection(
-      userBadges,
-      presenter,
-      compact,
-    )
+  for (const { default: it } of allBadges) {
+    const presenter: BadgePresenter = it
+    const newBadges: Badge[] = []
+    const grant = badgeCollection(newBadges)
     presenter.present(data, grant)
+
+    if (newBadges.length === 0) {
+      continue
+    }
+
+    // Enhance badges with image URLs.
+    for (const b of newBadges) {
+      const baseDir = path.basename(path.dirname(fileURLToPath(presenter.url)))
+      b.image = `https://github.com/my-badges/my-badges/blob/master/src/all-badges/${baseDir}/${b.id}.png?raw=true`
+    }
+
+    // Merge existing userBadges with newBadges.
+    if (compact && presenter.tiers) {
+      const newHighestTierBadge = newBadges.reduce((prev, curr) => {
+        return prev.tier > curr.tier ? prev : curr
+      })
+
+      const existingBadgeIndex = userBadges.findIndex((x) =>
+        (presenter.badges as ID[]).includes(x.id),
+      )
+      if (existingBadgeIndex === -1) {
+        userBadges.push(newHighestTierBadge)
+      } else if (
+        newHighestTierBadge.tier > userBadges[existingBadgeIndex].tier
+      ) {
+        userBadges[existingBadgeIndex] = newHighestTierBadge
+      }
+    } else {
+      for (const badge of newBadges) {
+        const index = userBadges.findIndex((x) => x.id === badge.id)
+        if (index === -1) {
+          userBadges.push(badge)
+        } else {
+          userBadges[index] = badge
+        }
+      }
+    }
   }
 
   if (pickBadges.length > 0) {
test/stars.test.ts
@@ -7,11 +7,7 @@ import { Data } from '../src/collect/collect.js'
 describe('stars', () => {
   it('counts and renders as expected', () => {
     const badges: Badge[] = []
-    const grant = badgeCollection(
-      badges,
-      starsPresenter,
-      true,
-    )
+    const grant = badgeCollection(badges, starsPresenter, true)
     const data: Data = {
       user: {} as Data['user'],
       pulls: {} as Data['pulls'],