Home Reference Source

src/js/molecules/constant.js

import Atom from '../prototypes/atom'
import GlobalVariables from '../globalvariables.js'

/**
 * This class creates the constant atom instance which can be used to define a numerical constant.
 */
export default class Constant extends Atom{
    
    /**
     * Creates a new constant atom.
     * @param {object} values - An object of values. Each of these values will be applied to the resulting atom.
     */ 
    constructor(values){
        super(values)
        
        /**
         * This atom's type
         * @type {string}
         */
        this.type = 'constant'
        /**
         * This atom's name
         * @type {string}
         */
        this.name = 'Constant'
        /**
         * This atom's type
         * @type {string}
         */
        this.atomType = 'Constant'
        /** 
         * A description of this atom
         * @type {string}
         */
        this.description = "Defines a mathematical constant."
        /**
         * This atom's height as drawn on the screen
         */
        this.height = 16
        /**
         * A flag to indicate if this constant should be evolved by genetic algorithms
         * @type {boolean}
         */
        this.evolve = false
        /**
         * Minimum value to be used when evolving constant
         * @type {float}
         */
        this.min = 0
        /**
         * Maximum value to be used when evolving constant
         * @type {float}
         */
        this.max = 20
        
        /**
         * The default value for the constant
         * @type {float}
         */
        this.value = 10
        
        this.setValues(values)
        
        this.addIO('output', 'number', this, 'number', 10)
        
        this.decreaseToProcessCountByOne()  //Since there is nothing upstream this needs to be removed from the list here
        
        //This is done wrong. We should not be saving the value in the io values
        if (typeof this.ioValues == 'object') {
            this.value = this.ioValues[0].ioValue
            this.output.value = this.value
        }
        
    }
    
    /**
     * Draw the Bill of material atom which has a BOM icon.
     */ 
    draw() {
        
        super.draw("rect")
        
    }
    
    /**
     * Set's the output value and shows the atom output on the 3D view.
     */ 
    updateValue(){
        this.value = this.output.getValue()  //We read from the output because it is set by the sidebar because constants have no inputs
        this.output.setValue(this.value)
        this.output.ready = true

        //Write to this's path just so that we know it has happened and don't load this again next time the project is opened
        try{
            const values = {op: "text", value:this.value, writePath: this.path }
            window.ask(values)
        }catch(err){this.setAlert(err)}
    }
    
    /**
     * Starts propagation from this atom if it is not waiting for anything up stream.
     */ 
    beginPropagation(){
        //Check to see if a value already exists. Generate it if it doesn't.
        if(!GlobalVariables.availablePaths.includes(this.path)){
            //Triggers inputs with nothing connected to begin propagation
            this.updateValue()
        }
    }
    
    /**
     * Sets all the input and output values to match their associated atoms.
     */
    loadTree(){
        return this.value
    }
    
    /**
     * Add entries for name and value to the side bar. Note: I think that should happen automatically and this function can be deleted. Please test that future self.
     */ 
    updateSidebar(){
        //updates the sidebar to display information about this node
        
        var valueList = super.updateSidebar() //call the super function
        this.createEditableValueListItem(valueList,this,'name', 'Name', false)
        this.createEditableValueListItem(valueList,this.output,'value', 'Value', true)
        
        this.createCheckbox(valueList,"Evolve",this.evolve,(event)=>{
            if(event.target.checked){
                this.evolve = true
                this.updateSidebar()
            } else{
                this.evolve = false
                this.updateSidebar()
            }
        })
        
        if(this.evolve){
            this.createEditableValueListItem(valueList,this,'min', 'Min', true)
            this.createEditableValueListItem(valueList,this,'max', 'Max', true)
        }
    }
    
    /**
     * Used to walk back out the tree generating a list of constants...used for evolving
     */ 
    walkBackForConstants(callback){
        //If this constant can evolve then add it to the target list
        if(this.evolve){
            callback(this)
        }
    }
    
    /**
     * Add the value to be saved to the object saved for this molecule.
     */ 
    serialize(values){
        //Save the IO value to the serial stream
        var valuesObj = super.serialize(values)
        
        valuesObj.ioValues = [{
            name: 'number',
            ioValue: this.output.getValue()
        }]
        
        valuesObj.evolve = this.evolve
        valuesObj.min = this.min
        valuesObj.max = this.max
        
        return valuesObj
        
    }

    /**
     * Send the value of this atom to the 3D display. Used to display the number
     */ 
    sendToRender(){
        //Send code to jotcad to render
        try{
            const values = {op: "text", value:this.output.getValue(), writePath: this.path }
            const {answer} = window.ask(values)
            answer.then( () => {
                GlobalVariables.writeToDisplay(this.path)
            })
        }
        catch(err){
            this.setAlert(err)
        }

    }
    
}