Home Identifier Source Repository

src/lib/find-leaf-requirements.js

import map from 'lodash/collection/map'
import compact from 'lodash/array/compact'
import isRequirementName from './is-requirement-name'
import isPlainObject from 'lodash/lang/isPlainObject'
import keys from 'lodash/object/keys'
import some from 'lodash/collection/some'
import flatten from 'lodash/array/flatten'

/**
 * Searches recursively through a requirement tree to find all of the
 * leaf requirements – all of the requirements with no children.
 *
 * @param {Requirement} requirement - the root requirement
 * @returns {Course[]} - the leaf children
 */
export default function findLeafRequirements(requirement) {
	// Time to muse. Just what is a "requirement with no children?"
	// I think that it's just that – a requirement with no children;
	// that is, one with no properties that pass the isRequirementName check.
	// If there are any children, then we call this func on each of them.
	// It should eventually return an array of all of the leaf children.

	// if it's not an object, return instantly.
	if (!isPlainObject(requirement)) {
		return null
	}

	// we've gone too far down!
	if (requirement.$type !== 'requirement') {
		return null
	}

	if (requirement.computed === true) {
		return [requirement]
	}

	// if there are no keys in this object which are requirement names,
	// then we've found a leaf requirement! return it.
	if (!some(keys(requirement), isRequirementName)) {
		return requirement
	}

	// otherwise, run findLeafRequirements over the object, to descend further
	// down the tree of madness.
	return compact(flatten(map(requirement, findLeafRequirements)))
}