UNPKG

maplestorysea-mcp-server

Version:

NEXON MapleStory SEA API MCP Server for Claude Desktop - Complete character info, union details, guild data, rankings optimized for SEA servers

272 lines 9.38 kB
"use strict"; /** * Ranking system utilities */ Object.defineProperty(exports, "__esModule", { value: true }); exports.RankingCacheKeys = exports.GuildRankingType = exports.RankingType = void 0; exports.validatePage = validatePage; exports.validateRankingType = validateRankingType; exports.validateGuildRankingType = validateGuildRankingType; exports.calculateRankingPosition = calculateRankingPosition; exports.calculatePageFromPosition = calculatePageFromPosition; exports.formatRankingEntry = formatRankingEntry; exports.formatNumber = formatNumber; exports.findCharacterPosition = findCharacterPosition; exports.findGuildPosition = findGuildPosition; exports.parseRankingResponse = parseRankingResponse; exports.mergeRankingPages = mergeRankingPages; exports.calculateRankingStats = calculateRankingStats; /** * Ranking types supported by the API */ var RankingType; (function (RankingType) { RankingType["OVERALL"] = "overall"; RankingType["UNION"] = "union"; RankingType["GUILD"] = "guild"; RankingType["DOJANG"] = "dojang"; RankingType["THESEED"] = "theseed"; RankingType["ACHIEVEMENT"] = "achievement"; })(RankingType || (exports.RankingType = RankingType = {})); /** * Guild ranking types */ var GuildRankingType; (function (GuildRankingType) { GuildRankingType[GuildRankingType["FLAG_RACE"] = 0] = "FLAG_RACE"; GuildRankingType[GuildRankingType["GUILD_POWER"] = 1] = "GUILD_POWER"; })(GuildRankingType || (exports.GuildRankingType = GuildRankingType = {})); /** * Validate page number for ranking queries */ function validatePage(page) { if (!Number.isInteger(page) || page < 1) { throw new Error('Page number must be a positive integer starting from 1'); } if (page > 200) { throw new Error('Page number cannot exceed 200'); } } /** * Validate ranking type */ function validateRankingType(type) { const validTypes = Object.values(RankingType); if (!validTypes.includes(type)) { throw new Error(`Invalid ranking type. Valid types: ${validTypes.join(', ')}`); } } /** * Validate guild ranking type */ function validateGuildRankingType(type) { const validTypes = Object.values(GuildRankingType).filter((v) => typeof v === 'number'); if (!validTypes.includes(type)) { throw new Error(`Invalid guild ranking type. Valid types: ${validTypes.join(', ')}`); } } /** * Calculate ranking position from page and index */ function calculateRankingPosition(page, index, pageSize = 200) { return (page - 1) * pageSize + index + 1; } /** * Calculate page from ranking position */ function calculatePageFromPosition(position, pageSize = 200) { return Math.ceil(position / pageSize); } /** * Format ranking data for display */ function formatRankingEntry(entry, position) { if (!entry) return entry; return { ...entry, displayRanking: position || entry.ranking || entry.guild_ranking || 0, formattedLevel: entry.character_level ? `Lv.${entry.character_level}` : undefined, formattedExp: entry.character_exp ? formatNumber(entry.character_exp) : undefined, formattedGuildLevel: entry.guild_level ? `Lv.${entry.guild_level}` : undefined, formattedMemberCount: entry.guild_member_count ? `${entry.guild_member_count} members` : undefined, }; } /** * Format large numbers with commas */ function formatNumber(num) { const number = typeof num === 'string' ? parseInt(num, 10) : num; if (isNaN(number)) return '0'; return number.toLocaleString('en-US'); } /** * Find character position in ranking data */ function findCharacterPosition(rankings, characterName, currentPage = 1, pageSize = 200) { if (!rankings || !Array.isArray(rankings)) { return { found: false }; } const normalizedName = characterName.toLowerCase().trim(); for (let i = 0; i < rankings.length; i++) { const entry = rankings[i]; const entryName = (entry.character_name || '').toLowerCase().trim(); if (entryName === normalizedName) { const position = calculateRankingPosition(currentPage, i, pageSize); return { found: true, position, entry: formatRankingEntry(entry, position), }; } } return { found: false }; } /** * Find guild position in ranking data */ function findGuildPosition(rankings, guildName, currentPage = 1, pageSize = 200) { if (!rankings || !Array.isArray(rankings)) { return { found: false }; } const normalizedName = guildName.toLowerCase().trim(); for (let i = 0; i < rankings.length; i++) { const entry = rankings[i]; const entryName = (entry.guild_name || '').toLowerCase().trim(); if (entryName === normalizedName) { const position = calculateRankingPosition(currentPage, i, pageSize); return { found: true, position, entry: formatRankingEntry(entry, position), }; } } return { found: false }; } /** * Generate ranking cache keys */ exports.RankingCacheKeys = { overall: (worldName, worldType, className, page, date) => { const parts = ['sea_ranking_overall']; if (worldName) parts.push(`world:${worldName}`); if (worldType) parts.push(`type:${worldType}`); if (className) parts.push(`class:${className}`); if (page) parts.push(`page:${page}`); if (date) parts.push(`date:${date}`); return parts.join(':'); }, union: (worldName, page, date) => { const parts = ['sea_ranking_union']; if (worldName) parts.push(`world:${worldName}`); if (page) parts.push(`page:${page}`); if (date) parts.push(`date:${date}`); return parts.join(':'); }, guild: (worldName, rankingType, page, date) => { const parts = ['sea_ranking_guild', `world:${worldName}`, `type:${rankingType}`]; if (page) parts.push(`page:${page}`); if (date) parts.push(`date:${date}`); return parts.join(':'); }, characterPosition: (characterName, worldName, className) => { const normalizedName = characterName.trim().toLowerCase().replace(/\s+/g, ''); const parts = ['sea_char_position', `name:${normalizedName}`]; if (worldName) parts.push(`world:${worldName}`); if (className) parts.push(`class:${className}`); return parts.join(':'); }, guildPosition: (guildName, worldName, rankingType) => { const normalizedName = guildName.trim().toLowerCase().replace(/\s+/g, ''); return `sea_guild_position:${worldName}:${rankingType}:${normalizedName}`; }, }; /** * Parse ranking response and add metadata */ function parseRankingResponse(response, page = 1) { const rankings = response.ranking || []; const currentPage = page; return { rankings: rankings.map((entry, index) => formatRankingEntry(entry, calculateRankingPosition(currentPage, index))), pagination: { currentPage, hasNextPage: rankings.length >= 200, // Assume full page means more data hasPreviousPage: currentPage > 1, totalEntries: rankings.length, }, metadata: { lastUpdate: new Date().toISOString(), rankingType: response.ranking_type || 'unknown', worldName: response.world_name, }, }; } /** * Merge ranking data from multiple pages for position search */ function mergeRankingPages(pages) { const merged = []; pages.forEach((page, pageIndex) => { if (page.ranking && Array.isArray(page.ranking)) { page.ranking.forEach((entry, entryIndex) => { const position = calculateRankingPosition(pageIndex + 1, entryIndex); merged.push(formatRankingEntry(entry, position)); }); } }); return merged; } /** * Calculate ranking statistics */ function calculateRankingStats(rankings) { if (!rankings || rankings.length === 0) { return { totalEntries: 0, levelRange: { min: 0, max: 0 }, averageLevel: 0, }; } const levels = rankings.map((entry) => entry.character_level || 0).filter((level) => level > 0); const guildNames = rankings .map((entry) => entry.character_guild_name || entry.guild_name) .filter((name) => name && name.trim()) .reduce((acc, name) => { acc[name] = (acc[name] || 0) + 1; return acc; }, {}); const topGuilds = Object.entries(guildNames) .sort(([, a], [, b]) => b - a) .slice(0, 5) .map(([name]) => name); const result = { totalEntries: rankings.length, levelRange: { min: levels.length > 0 ? Math.min(...levels) : 0, max: levels.length > 0 ? Math.max(...levels) : 0, }, averageLevel: levels.length > 0 ? Math.round(levels.reduce((a, b) => a + b, 0) / levels.length) : 0, }; if (topGuilds.length > 0) { result.topGuilds = topGuilds; } return result; } //# sourceMappingURL=ranking-utils.js.map