function TurkeyLayer( name, layerNumber1, turkeyModel, ovenModel ){ var that = this; this.name = name; this.layerNumber=layerNumber1; this.waterLost = 0; this.finalTemperature = 20; this.cookCondition = "Raw"; return { updateTemperatureTick: function(){ that.finalTemperature = turkeyModel.globTemp[that.layerNumber] console.log(turkeyModel.globTemp) that.waterLost = that.waterLost + UtilityFunctions.waterLoss( that.finalTemperature ); that.cookCondition = UtilityFunctions.cookCondition(that.waterLost); if(DEBUG) console.log( that.name + ": "+ that.waterLost + " " + that.cookCondition + " " + that.finalTemperature + " C" ); }, getCondition: function(){ return that.cookCondition; }, getTemperature: function(){ return that.finalTemperature; } } } function TurkeyModel( weight, ovenModel ){ this.density = 700; // kg/m3 Assuming Density of Water 1000 kg/m3 this.cp = 2810; // 2810 J/kg K for Turkey. Extra is to semi-account for water evaporation energy this.heatConvection = 9; // W/m2 K Some Reasonable estimate for natural Convection. Change as needed. 5-25 this.thermalConduct = 0.412; // W/m K // Chicken this.skin = {}; this.body = {}; this.core = {}; this.splitsNum = 20; console.log(UtilityFunctions.lbs2kgs(weight)) this.totalRadius = UtilityFunctions.calculateRadius( UtilityFunctions.lbs2kgs(weight), this.density ); this.totalLayers = [ new TurkeyLayer("Skin", this.splitsNum-1, this, ovenModel ), new TurkeyLayer("Body", this.splitsNum-4, this, ovenModel ), new TurkeyLayer("Core", 0, this, ovenModel ) ]; // Whenever temperature is changed this.updateLayerTemps = function() { this.globTemp = UtilityFunctions.transientSphereSeries( this.density, this.thermalConduct, this.heatConvection, this.cp, this.totalRadius, ovenModel.tempInfini, this.splitsNum, this.deltar, this.globTemp, this.pointRadius ); for (var i in this.totalLayers ){ this.totalLayers[i].updateTemperatureTick(); } }; this.resetLayerTemps = function() { for (var i in this.totalLayers ) { this.totalLayers[i].resetLayerTemps(); } }; //Sheen Model Stuff this.globTemp=[]; this.pointRadius = [] this.splitsNum = 20; this.deltar = this.totalRadius/this.splitsNum; //20 Data Points this.initializePoints = function() { var step = ( this.totalRadius - this.deltar ) / ( this.splitsNum - 1 ); for (var i = 0; ithis.tempInfini ){ this.tempInfini = this.tempInfini + error*proportional; } else if( this.setTemperrorTolerance ) { return(true); } } return { getTurkeyState: function(){ return { "skin" : { "temp": turkey.totalLayers[0].getTemperature(), "cond": turkey.totalLayers[0].getCondition() }, "body" : { "temp": turkey.totalLayers[1].getTemperature(), "cond": turkey.totalLayers[1].getCondition() }, "core" : { "temp": turkey.totalLayers[2].getTemperature(), "cond": turkey.totalLayers[2].getCondition() } }; }, changeTemp: function(setTemp){ if(DEBUG) console.log("temp changed to " + setTemp); that.setTemp = setTemp; }, // set the tempInfini setRawTemp: function(newTemp){ if(DEBUG) console.log("raw temp changed to" + that.tempInfini); that.tempInfini = newTemp; }, getRawTemp: function(){ return that.tempInfini; }, getCookTime: function(){ return that.globalTime; }, secondTick: function(){ that.globalTime = that.globalTime + 1; if ( that.equalizeTemp() ) { // Turn on oven light gameState.pubsub.publish( "OvenLight", "On" ); } else { // Turn off oven light gameState.pubsub.publish( "OvenLight", "Off" ); } if(DEBUG) console.log("Oven Temp " + that.tempInfini ) turkey.updateLayerTemps(); } } } UtilityFunctions = { // Cache the lambda if the Biot number does not change, to avoid expensive root-finding operations cachedBiot: null, cachedLambda: null, // Using Ratios for a rectangular Box Turkey calculateRadius: function(weight, density) { var ratioLvG=1.4; //1.4, Turkey length vs shoulder girth var ratioLvH=2; //2, Turkey length vs height from resting position var length = Math.pow(weight/((1/ratioLvG)*(1/ratioLvH)*density),(1/3)) var depth = 1/(ratioLvG /length); var height = 1/(ratioLvH /length); var simpleRadius = length/2; //Doesn't take into account equal Volume var rectangleVolume = depth*height*length; //m^3 Multiple by 1/4 to account for triangular shape and empty Space var complexRadius = Math.pow(rectangleVolume/((4/3)*Math.PI), 1/3); //Volume of 3D Box = 3D Sphere //if(DEBUG) console.log("Simple Radius " + simpleRadius + " Meters") //if(DEBUG) console.log("Complex Radius " + complexRadius + " Meters") return complexRadius; }, sphereVolume: function(radius) { return((4/3)*Math.PI*Math.pow(radius,3)) }, waterLoss: function(temperature) { return (Math.pow(10,(temperature-20)/80)-1) }, transientSphereSeries: function( density, thermalConduct, heatConvection, cp, rTotal, tempInfinity, splitsNum, deltar, globTemp,pointRadius) { //Not Global Stuff var r0 = rTotal; var deltat = 0.1 var alpha = thermalConduct/(density*cp) var h=heatConvection; for (var j=0; j<(1/deltat); j++ ) { var dTdr=[] // globTemp[splitsNum-1] should be last entry in globtemp for (var k=0; k=multiplier*600000) { return ["Fire", (cookValue-600000)/(multiplier*600000),"fire"]; } else if(cookValue>=multiplier*250000) { return ["Burnt", (cookValue-250000)/(multiplier*600000), "burnt"]; } else if (cookValue>=multiplier*150000) { return ["Dry", (cookValue-150000)/(multiplier*250000), "dry"]; } else if (cookValue>=multiplier*85000){ return ["Cooked", (cookValue-12000)/(multiplier*150000), "overcooked"]; } else if (cookValue>=multiplier*12000) { return ["Cooked", (cookValue-12000)/(multiplier*150000), "cooked"]; } else if (cookValue>=multiplier*10000){ return ["Undercooked", (cookValue-5000)/(multiplier*12000), "slightly cooked"]; } else if (cookValue>=multiplier*5000) { return ["Undercooked", (cookValue-5000)/(multiplier*12000), "undercooked"]; } else { return ["Raw", 1, "raw"]; } } } //Running the Program Stuff /* var ovenObject = new OvenModel(); var turkey = new TurkeyModel(9, ovenObject); globalTime=0; setInterval(function(){ovenObject.secondTick();},1000); */