MCPcopy Create free account
hub / github.com/p2r3/convert / costFunction

Method costFunction

src/TraversionGraph.ts:234–292  ·  view source on GitHub ↗

* Cost function for calculating the cost of converting from one format to another using a specific handler.

(
        from: { format: FileFormat; index: number; },
        to: { format: FileFormat; index: number; },
        strictCategories: boolean,
        handler: string,
        handlerIndex: number
    )

Source from the content-addressed store, hash-verified

232 * Cost function for calculating the cost of converting from one format to another using a specific handler.
233 */
234 private costFunction(
235 from: { format: FileFormat; index: number; },
236 to: { format: FileFormat; index: number; },
237 strictCategories: boolean,
238 handler: string,
239 handlerIndex: number
240 ) {
241 let cost = DEPTH_COST; // Base cost for each conversion step
242
243 const handlerPairs = new Map<string, string>(this.categoryChangeCosts.filter(c => c.handler)
244 .map(c => [`${c.from}->${c.to}`, c.handler] as [string, string]));
245 // Calculate category change cost
246 const fromCategory = from.format.category || from.format.mime.split("/")[0];
247 const toCategory = to.format.category || to.format.mime.split("/")[0];
248 if (fromCategory && toCategory) {
249 const fromCategories = Array.isArray(fromCategory) ? fromCategory : [fromCategory];
250 const toCategories = Array.isArray(toCategory) ? toCategory : [toCategory];
251 if (strictCategories) {
252 cost += this.categoryChangeCosts.reduce((totalCost, c) => {
253 // If the category change defined in CATEGORY_CHANGE_COSTS matches the categories of the formats, add the specified cost. Otherwise, if the categories are the same, add no cost. If the categories differ but no specific cost is defined for that change, add a default cost.
254 if (fromCategories.includes(c.from)
255 && toCategories.includes(c.to)
256 && (!c.handler || c.handler === handler.toLowerCase())
257 )
258 return totalCost + c.cost;
259 return totalCost + DEFAULT_CATEGORY_CHANGE_COST;
260 }, 0);
261 }
262 else if (!fromCategories.some(c => toCategories.includes(c))) {
263 let costs = this.categoryChangeCosts.filter(c =>
264 fromCategories.includes(c.from)
265 && toCategories.includes(c.to)
266 && (
267 (!c.handler && handlerPairs.get(`${c.from}->${c.to}`) !== handler.toLowerCase())
268 || c.handler === handler.toLowerCase()
269 )
270 );
271 if (costs.length === 0) cost += DEFAULT_CATEGORY_CHANGE_COST; // If no specific cost is defined for this category change, use the default cost
272 else cost += Math.min(...costs.map(c => c.cost)); // If multiple category changes are involved, use the lowest cost defined for those changes. This allows for more nuanced cost calculations when formats belong to multiple categories.
273 }
274 }
275 else if (fromCategory || toCategory) {
276 // If one format has a category and the other doesn't, consider it a category change
277 // Should theoretically never be encountered, unless the MIME type is misspecified
278 cost += DEFAULT_CATEGORY_CHANGE_COST;
279 }
280
281 // Add cost based on handler priority
282 cost += HANDLER_PRIORITY_COST * handlerIndex;
283
284 // Add cost based on format priority
285 const handlerObj = this.handlers.find(h => h.name === handler)
286 cost += FORMAT_PRIORITY_COST * (handlerObj?.supportedFormats?.findIndex(f => f.mime === to.format.mime) ?? 0);
287
288 // Add cost multiplier for lossy conversions
289 if (!to.format.lossless) cost *= LOSSY_COST_MULTIPLIER;
290
291 return cost;

Callers 1

initMethod · 0.95

Calls 1

getMethod · 0.45

Tested by

no test coverage detected