MCPcopy Create free account
hub / github.com/codecombat/codecombat / sortThangComponents

Method sortThangComponents

app/models/Level.js:351–416  ·  view source on GitHub ↗
(thangs, levelComponents, parentType)

Source from the content-addressed store, hash-verified

349 }
350
351 sortThangComponents (thangs, levelComponents, parentType) {
352 // Here we have to sort the Components by their dependencies.
353 // It's a bit tricky though, because we don't have either soft dependencies or priority levels.
354 // Example: Programmable must come last, since it has to override any Component-provided methods that any other Component might have created. Can't enumerate all soft dependencies.
355 // Example: Plans needs to come after everything except Programmable, since other Components that add plannable methods need to have done so by the time Plans is attached.
356 // Example: Collides doesn't depend on Allied, but if both exist, Collides must come after Allied. Soft dependency example. Can't just figure out a proper priority to take care of it.
357 // Example: Moves doesn't depend on Acts, but if both exist, Moves must come after Acts. Another soft dependency example.
358 // Decision? Just special case the sort logic in here until we have more examples than these two and decide how best to handle most of the cases then, since we don't really know the whole of the problem yet.
359 // TODO: anything that depends on Programmable will break right now.
360
361 const originalsToComponents = _.indexBy(levelComponents, 'original') // Optimization for speed
362 const alliedComponent = _.find(levelComponents, { name: 'Allied' })
363 const actsComponent = _.find(levelComponents, { name: 'Acts' })
364
365 return (() => {
366 const result = []
367 for (const thang of Array.from(thangs != null ? thangs : [])) {
368 const originalsToThangComponents = _.indexBy(thang.components, 'original')
369 const sorted = []
370 const visit = function (c, namesToIgnore) {
371 let c2
372 if (Array.from(sorted).includes(c)) { return }
373 const lc = originalsToComponents[c.original]
374 if (!lc) { console.error(thang.id || thang.name, 'couldn\'t find lc for', c, 'of', levelComponents) }
375 if (!lc) { return }
376 if (namesToIgnore && Array.from(namesToIgnore).includes(lc.name)) { return }
377 if (lc.name === 'Plans') {
378 // Plans always comes second-to-last, behind Programmable
379 for (c2 of Array.from(thang.components)) { visit(c2, [lc.name, 'Programmable']) }
380 } else if (lc.name === 'Programmable') {
381 // Programmable always comes last
382 for (c2 of Array.from(thang.components)) { visit(c2, [lc.name]) }
383 } else {
384 for (const d of Array.from(lc.dependencies || [])) {
385 c2 = originalsToThangComponents[d.original]
386 if (!c2) {
387 let dependent = originalsToComponents[d.original]
388 dependent = (dependent != null ? dependent.name : undefined) || d.original
389 console.error(parentType, thang.id || thang.name, 'does not have dependent Component', dependent, 'from', lc.name)
390 }
391 if (c2) { visit(c2) }
392 }
393 if ((lc.name === 'Collides') && alliedComponent) {
394 const allied = originalsToThangComponents[alliedComponent.original]
395 if (allied) {
396 visit(allied)
397 }
398 }
399 if ((lc.name === 'Moves') && actsComponent) {
400 const acts = originalsToThangComponents[actsComponent.original]
401 if (acts) {
402 visit(acts)
403 }
404 }
405 }
406 // console.log thang.id, 'sorted comps adding', lc.name
407 return sorted.push(c)
408 }

Callers 2

serializeMethod · 0.95
createAddThangMethod · 0.80

Calls

no outgoing calls

Tested by

no test coverage detected