• Create MangaMatchResult for single manga with confidence scores and sources.

    Combines AniList matches with confidence scores and Comick/MangaDex source info. Applies confidence floor boost for matches that satisfied custom accept rules:

    • Exact matches: boosted to 85% confidence minimum
    • Other matches: boosted to 75% confidence minimum

    Parameters

    • manga: KenmeiManga

      Kenmei manga entry.

    • potentialMatches: (AniListManga & { matchedAcceptRule?: CustomRule })[]

      AniList matches for this manga (may have matchedAcceptRule tracking).

    • comickSourceMap: Map<
          number,
          {
              title: string;
              slug: string;
              comickId: string;
              isFoundViaComick: boolean;
          },
      >

      Map of manga ID to Comick source info.

    • mangaDexSourceMap: Map<
          number,
          {
              title: string;
              slug: string;
              mangaDexId: string;
              isFoundViaMangaDex: boolean;
          },
      >

      Map of manga ID to MangaDex source info.

    Returns MangaMatchResult

    Complete match result with confidence and source info.

    export function createMangaMatchResult(
    manga: KenmeiManga,
    potentialMatches: Array<AniListManga & { matchedAcceptRule?: CustomRule }>,
    comickSourceMap: Map<
    number,
    {
    title: string;
    slug: string;
    comickId: string;
    isFoundViaComick: boolean;
    }
    >,
    mangaDexSourceMap: Map<
    number,
    {
    title: string;
    slug: string;
    mangaDexId: string;
    isFoundViaMangaDex: boolean;
    }
    >,
    ): MangaMatchResult {
    // Fix mapping to create proper MangaMatch objects with Comick source info
    const normalizedMatches = potentialMatches.map((match) => {
    const sourceInfo = getSourceInfo(
    match.id,
    comickSourceMap,
    mangaDexSourceMap,
    );

    let confidence = calculateConfidence(manga.title, match);

    // Apply confidence floor boost if accept rule matched
    if (match.matchedAcceptRule) {
    const isExactMatch =
    manga.title.toLowerCase() === match.title?.romaji?.toLowerCase() ||
    manga.title.toLowerCase() === match.title?.english?.toLowerCase();
    const minConfidence = isExactMatch
    ? ACCEPT_RULE_CONFIDENCE_FLOOR_EXACT
    : ACCEPT_RULE_CONFIDENCE_FLOOR_REGULAR;

    if (confidence < minConfidence) {
    console.debug(
    `[MangaSearchService] ⭐ Boosting confidence from ${(confidence * 100).toFixed(0)}% to ${(minConfidence * 100).toFixed(0)}% for "${match.title?.romaji || match.title?.english}" (accept rule match)`,
    );
    confidence = minConfidence;
    }
    }

    return {
    manga: match,
    confidence,
    comickSource: comickSourceMap.get(match.id),
    mangaDexSource: mangaDexSourceMap.get(match.id),
    sourceInfo,
    };
    });

    return {
    kenmeiManga: manga,
    anilistMatches: normalizedMatches,
    selectedMatch:
    normalizedMatches.length > 0 ? normalizedMatches[0].manga : undefined,
    status: "pending",
    };
    }