Overview
AMPI offers two main concepts for doing calculations: Scores and Blackboxes. Blackboxes are meant to evaluate one or several part Properties. That means a blackbox looks at the value of one property (can also be several properties if they are correlated) and decides whether that value is rather good (for AM) or rather bad (for AM).
Scores are meant to evaluate one or several Blackboxes, to produce an overall assessment of a part’s characteristics. Through reports and charts, the score results can then be shown to users.
The following example illustrates a typical setup:
Blackboxes and Scores are written in Javascript. For making adjustments to the calculation logic, it is helpful to have some prior exposure to any kind of scriptwriting or programming
Blackboxes
Defining blackboxes
Blackboxes are defined in the admin panel under
Home › B3_Ampi › Blackboxes
When defining blackboxes, the following fields are available.
Name
The name of the blackbox
Description
Additional description for the blackbox. Currently not displayed anywhere.
Script
The core of the blackbox is a script written in Javascript
Slug
Unique identifier of that blackbox. Used to reference this blackbox from a score.
Writing blackbox scripts
A blackbox can be considered a function that returns a value or an object.
Blackboxes can access a part’s property values through the property’s Variable namespace and Variable name:
variables.<Variable namespace>.<Variable name>
Variable namespace and Variable name are configured on the property itself.
By convention, blackboxes used for tech and econ scores have a return value between 0..1 representing a percentage between 0-100%.
Example:
A blackbox assessing the integer property Lead time (days)
// Lead time intervals const intervals = [8, 60] // Reading lead time from the property const leadTime = variables.custom.leadTimeExact if (leadTime === null) return null return mapInterval(leadTime, intervals[0], intervals[1])
Example:
A blackbox assessing the boolean property Qualification needed
const propertyValue = variables.custom.qualificationNeeded switch (propertyValue) { case true: return 0.35 case false: return 1.0 default: return null }
Scores
Scores can aggregate blackbox results into an overall result
Defining scores
Scores are defined in the admin panel under
Home › B3_Ampi › Scores
When defining scores, the following fields are available.
Name
The display name of the score.
Description
Additional description for the score. Currently not displayed anywhere in the UI.
Script
The core of the score is a script written in Javascript
Slug
Unique identifier of that score. Used as part of the column name in CSV exports.
Filterable
If selected, this score will be available for filtering on the part list. Should only be enabled for numerical scores. Only scores marked as filterable will be included in CSV exports.
Writing score scripts
A score can be considered a function that returns an object with a result
value. The result value can then be displayed in charts.
Example:
A basic calculated score
const calculated_result = 0.3 + 0.5 return { result: calculated_result, }
All blackboxes are calculated before calculating scores. Within scores scripts, blackbox results are accessible through the results
variable. Hence scores can access blackbox results through the results
variable and the corresponding blackbox slug.
Example:
A score script retrieving the result of the BbEconLeadTimeExact
blackbox
// Slug of the blackbox that I want to retrieve const LEAD_TIME_EXACT = 'BbEconLeadTimeExact' // Retrieving blackbox result const value = results[LEAD_TIME_EXACT].result
Tech and Econ scores
Tech and Econ scores are numerical scores that calculate the technical and economic suitability of a part within a range of [0, 1]. Values towards 0 indicate poor suitability, values towards 1 indicate good suitability for AM.
The general setup of Tech and Econ scores in AMPI is the calculation of the Weighted Average (Wikipedia). In the weighted average score calculation, we calculate the average of the results of individual blackboxes and give a weight according to their importance or impact on the overall score.
The weights of the blackbox can be adjusted to indicate how much impact an individual blackbox should have on the score. By convention, the weights are between 0..1. Values towards 0 indicate low impact, values towards 1 indicate a strong impact on the score result.
For a complete example of an econ score, see the Appendix
Text scores
The result of text scores is a String (text) - as opposed to numerical scores that produce numerical results. They can be used in charts with the type Text.
Text scores need to return an object with two variables
result
- contains the results string, can be markdown formattedtype
- variable with the value'text'
Example:
A simple text score
const result_string = 'Text with __Markdown__ syntax' return { result: result_string, type: 'text', }
For a more comprehensive example see the Appendix.
Helper functions
Helper functions are functions that are often used throughout multiple blackboxes or scores. To avoid defining such functions in each blackbox where it is used, they can just be defined once as a helper function. Then all blackboxes and scores can just use them without the need to define them redundantly.
Example helper function
// Maps an input from a flexible interval into the corresponding value within standard interval [0, 1] function mapInterval(val, a, b, c = 0.0, d = 1.0) { return Math.min(1, Math.max(0, ((val - a) * (d - c)) / (b - a) + c)) }
For an example where a helper function is used, see the example blackbox for Lead time (days) above.
Helper functions can be defined in the admin panel under
Home › B3_Ampi › Helper functions
How to debug blackboxes and scores
The results of blackbox and score calculations can be verified in several places in the admin panel
Verifying all calculations of one particular part
Go to Parts
Home › B3_Ampi › PartsFind the part that you are interested in and open the details
Scroll down past the properties
You’ll reach a table with all score results for this part and a table with all blackbox results just below.
Appendix
Example
Full econ score script
// Blackbox IDs const LEAD_TIME_EXACT = 'BbEconLeadTimeExact' const MIN_ORDER_QTY = 'BbEconMinOrderQuantity' const PART_PRICE = 'BbEconCurrentPartPrice' const PRICE_PER_KG = 'BbEconPricePerKg' const QUALIFICATION_NEEDED = 'BbEconQualificationNeeded' const SELECTION_LOGIC_ECON = 'BbEconSelectionLogic' // Define blackbox weights const blackboxes = [ { name: 'Part price', weight: 0.5, id: PART_PRICE, }, { name: 'Lead time', weight: 0.7, id: LEAD_TIME_EXACT, }, { name: 'Price/kg', weight: 0.5, id: PRICE_PER_KG }, { name: 'Sel. Logic', weight: 1.0, id: SELECTION_LOGIC_ECON, }, ] let resultsBlackboxes = new Set() let score = 0 let weightsum = 0 let weighttotal = 0 for (const { id, name, weight } of blackboxes) { // Retrieve blackbox result const value = results[id].result if (value !== null) { score += weight * value weightsum += weight resultsBlackboxes.add({ name: name, weight: weight, id: id, result: value, }) } weighttotal += weight } let result = score / weightsum let certainty = weightsum / weighttotal return { result: result, certainty: certainty, resultsBlackboxes: resultsBlackboxes, }
Example
Text score for complexity
// Blackbox slugs const COMPLEXITY = 'ComplexityExact' const complexityExact = results[COMPLEXITY].result let result_string if (complexityExact !== null) { let complexityChoice if (complexityExact < 1.55) { complexityChoice = 'low' } else if (complexityExact < 2.1) { complexityChoice = 'medium' } else complexityChoice = 'high' result_string = 'Complexity: ' + complexityExact.toFixed(2) + ' (' + complexityChoice + ')' } else result_string = 'Insufficient data to calculate Complexity' return { result: result_string, type: 'text', }