Compare commits

...

25 Commits

Author SHA1 Message Date
Robert Chen 59b74b168d Recommended change 11 years ago
Scott Mobley dd39c692d4 Merge branch 'formula' of https://github.com/fernjager/game-off-2013 into formula 11 years ago
Scott Mobley 97fc37f40c In case I get side-tracked. Here is Sheen's WIP model. 11 years ago
Robert Chen ac516d2b27 Update README.md 11 years ago
Zott820 fa3def9dbd Spelling and website updates 11 years ago
Zott820 7963ffee91 Temporary Commit 11 years ago
Scott Mobley 59532c039f Main Menu Screen Added for Read-me 11 years ago
Scott Mobley 198f7e97a9 Decent version of the formula. Seems to work alright for a couple different temperature ranges. Averaged around a 12lb turkey for about 4 hours to try and get it to 175 F. 11 years ago
Scott Mobley 167e8f7b41 Fixed a MAJOR bug with the formula. Now performs closer to expectations. It was a self inflicted case where the intial temperature was almost instantaneously being reset to the final temperature, despite it not being a formula restart condition. DAMN 11 years ago
Scott Mobley 6b0dffde85 A 'working' formula. It needs some tweaking to account for the skin heating up fastest BUT not having the greatest volume. 11 years ago
Scott Mobley 6630f8e84f Another Set of Failed Equations 11 years ago
Scott Mobley 44e4056aaf These formulas do not work well enough. Shifting to a pure cooking model. Abandoning the idea of water displacement. 11 years ago
Scott Mobley 9275d260fa Work continues on the formula. Backup before realism stripped from model. 11 years ago
Scott Mobley 925ca23bae Committing Audio In Chunks Now 11 years ago
Zott820 b5dc2bc8bd Update README.md 11 years ago
Zott820 302bc36260 Minimal Read-me for Branch 11 years ago
Scott Mobley b87537c250 Added some Audio to use 11 years ago
Scott Mobley 40b2667779 A 'working' transient model 11 years ago
Scott Mobley b5f88a27d7 Most recent formulas 11 years ago
Scott Mobley 725b0cd5a9 Adjusted the Tolerances for a good set of hopeful accuracy vs speed. 11 years ago
Scott Mobley 091ac61034 Transient Formula looks to be in good working order. That is, the roots appear correct compared to matlab generated results from a published paper. 11 years ago
Scott Mobley f67a7410e9 Under Guidance from a matlab project, I believe I have locked down the bisection method and the finding of good roots. I wanted to commit this before replacing some crucial chucks of the Transient Series method for testing. 11 years ago
Scott Mobley bf3bc66a48 More fooling around with the equations. Not much progress. Focusing now on lumpedCapacitance in a simple capacity. 11 years ago
Scott Mobley 654da49e2d Added a Bisection function that works for Biot values of 1, which unfortunately is not good enough. Better, but not much better than the previous transient model. 11 years ago
Scott Mobley 5d72b59901 Turkey formulas 11 years ago
  1. 68
      Audio/Audio Sources.txt
  2. BIN
      Audio/Cooking/Alarm Clock/Beep.wav
  3. BIN
      Audio/Cooking/Alarm Clock/DoubleBeep.wav
  4. BIN
      Audio/Cooking/Basting/1.wav
  5. BIN
      Audio/Cooking/Basting/122763__alienistcog__gurgles 1.wav
  6. BIN
      Audio/Cooking/Basting/122763__alienistcog__gurgles 2.wav
  7. BIN
      Audio/Cooking/Basting/122763__alienistcog__gurgles 3.wav
  8. BIN
      Audio/Cooking/Basting/122763__alienistcog__gurgles.wav
  9. BIN
      Audio/Cooking/Basting/125170__alienistcog__vicor-coffee-maker 1.wav
  10. BIN
      Audio/Cooking/Basting/125170__alienistcog__vicor-coffee-maker 2.wav
  11. BIN
      Audio/Cooking/Basting/155901__tiptoe84__spit.wav
  12. BIN
      Audio/Cooking/Basting/171336__brlproductions__gargle-then-spit 1.wav
  13. BIN
      Audio/Cooking/Basting/171336__brlproductions__gargle-then-spit 2.wav
  14. BIN
      Audio/Cooking/Basting/2.wav
  15. BIN
      Audio/Cooking/Basting/3.wav
  16. BIN
      Audio/Cooking/Basting/4.wav
  17. BIN
      Audio/Cooking/Fan/146251__ferdinger__suction-switched-off.wav
  18. BIN
      Audio/Cooking/Fan/146251__ferdinger__suction-switched-on.aiff
  19. BIN
      Audio/Cooking/Fan/146251__ferdinger__suction-switched-on.wav
  20. BIN
      Audio/Cooking/Fan/146251__ferdinger__suction-switched-on1.wav
  21. BIN
      Audio/Cooking/Oven Door/Door Slam Shut.wav
  22. BIN
      Audio/Cooking/Oven Door/Oven Door Open.wav
  23. BIN
      Audio/Cooking/Oven Door/Oven Door_Full_Close.mp3
  24. BIN
      Audio/Cooking/Oven Door/Oven Door_Full_Close.wav
  25. BIN
      Audio/Cooking/Oven Door/Oven_Door_Full_Open.mp3
  26. BIN
      Audio/Cooking/Oven Door/Oven_Door_Full_Open.wav
  27. BIN
      Audio/Cooking/Oven Door/Oven_Door_Peek_Close.mp3
  28. BIN
      Audio/Cooking/Oven Door/Oven_Door_Peek_Close.wav
  29. BIN
      Audio/Cooking/Oven Door/Oven_Door_Peek_Open.mp3
  30. BIN
      Audio/Cooking/Oven Door/Oven_Door_Peek_Open.wav
  31. BIN
      Audio/Cooking/Oven Door/RAW/Beeps and Toaster Oven.wav
  32. BIN
      Audio/Cooking/Roasting/32371__walter-odington__frying-pan-chicken-and-onion.wav
  33. BIN
      Audio/Events/Fire/189212__vurca__burning-fire.wav
  34. BIN
      Audio/Events/Fire/87564__sgak__fire Fire Start Louder.wav
  35. BIN
      Audio/Events/Fire/87564__sgak__fire Fire Start.wav
  36. BIN
      Audio/Events/Fire/87564__sgak__fire Loop.wav
  37. BIN
      Audio/Events/Fire/87564__sgak__fire.wav
  38. BIN
      Audio/GUI/1.wav
  39. BIN
      Audio/GUI/Click/63531__florian-reinke__click1.wav
  40. BIN
      Audio/GUI/Click/63532__florian-reinke__click2.wav
  41. BIN
      Audio/Store/Background Noises/131600__liam125__north-camp-railway-station-pa-announcements.wav
  42. BIN
      Audio/Store/Background Noises/202029__hykenfreak__notification-chime.wav
  43. BIN
      Audio/Store/Background Noises/72852__7by7__tannoy-announcement-jingle.wav
  44. BIN
      Audio/Store/Background Noises/83915__cognito-perceptu__cash-register1.wav
  45. BIN
      Audio/Store/Background Noises/83915__cognito-perceptu__cash-register2.wav
  46. BIN
      Audio/Store/Background Sounds/72565__wrinex__supermarkt-ms.wav
  47. BIN
      Audio/turkey_in_the_straw.mp3
  48. BIN
      Main-Screen-MockupV11-24.png
  49. BIN
      Price List.xlsx
  50. 67
      README.md
  51. 89
      js/AlternativeModels.js
  52. 263
      js/CookingFormula.js
  53. 289
      js/Sheen's Model - WIP/model.js
  54. 8
      js/Turkey.html

68
Audio/Audio Sources.txt

@ -0,0 +1,68 @@
Unless Otherwise noted, all sounds and music are in the public Domain.
---------------------------
Main Menu Music
turkey_in_the_straw.mp3
Composition Licence: Traditional, arr. first published between 1829 and 1834. This MP3 (or other media file) is in the public domain because its copyright has expired. This applies to the United States, where Works published prior to 1978 were copyright protected for a maximum of 75 years. See Circular 1 "COPYRIGHT BASICS" from the U.S. Copyright Office. Works published before 1924 are now in the public domain.
This file is also in the public domain in countries that figure copyright from the date of death of the artist (post mortem auctoris in this case George Washington Dixon 1801? âMarch 2, 1861), and that most commonly runs for a period of 50 to 70 years from December 31 of that year.
Performance Licence: The United States Air Force Band Web site is provided as a public service by the United States Air Force Band and Department of the Air Force.
Information presented on the United States Air Force Band site is considered public information and may be distributed or copied. Use of appropriate byline/photo/image credits is requested.
UPLOADED by Sookietex
---------------------------
freesound.org
Listed as file number, author, and title
32371__walter-odington__frying-pan-chicken-and-onion
36328__unclesigmund__coinbank - Crank Sound
63531__florian-reinke__click1
63532__florian-reinke__click2
72565__wrinex__supermarkt-ms
73261__jakobhandersen__click
87564__sgak__fire
142895__ceremonialchapstick__winchester-30-30-lever-action-eject-1
155441__wakey__buzz1
175678__saundklyp__tongue-click
184438__capslok__cash-register-fake
---------------------------
Store Background Music:
Title: Waterford
Artist: Kevin MacLeod
Genre: World
Length: 1:54
Bitrate: 286 kbps
Size: 3.88MB
Simple folk-inspired ditty. Source: Kevin MacLeod
---------------------------
Unused Music (Don't Cite this...yet)
-----------------------------------------------------------------------------------------------------------
Title: Improved Ice Cream Truck
Artist: Kevin MacLeod
Genre: Folk
Length: 0:51
Bitrate: 320 kbps
Size: 1.93MB
An improved version of a traditional Ice Cream Truck melody… whose actual title I forget.
---------------------------

BIN
Audio/Cooking/Alarm Clock/Beep.wav

Binary file not shown.

BIN
Audio/Cooking/Alarm Clock/DoubleBeep.wav

Binary file not shown.

BIN
Audio/Cooking/Basting/1.wav

Binary file not shown.

BIN
Audio/Cooking/Basting/122763__alienistcog__gurgles 1.wav

Binary file not shown.

BIN
Audio/Cooking/Basting/122763__alienistcog__gurgles 2.wav

Binary file not shown.

BIN
Audio/Cooking/Basting/122763__alienistcog__gurgles 3.wav

Binary file not shown.

BIN
Audio/Cooking/Basting/122763__alienistcog__gurgles.wav

Binary file not shown.

BIN
Audio/Cooking/Basting/125170__alienistcog__vicor-coffee-maker 1.wav

Binary file not shown.

BIN
Audio/Cooking/Basting/125170__alienistcog__vicor-coffee-maker 2.wav

Binary file not shown.

BIN
Audio/Cooking/Basting/155901__tiptoe84__spit.wav

Binary file not shown.

BIN
Audio/Cooking/Basting/171336__brlproductions__gargle-then-spit 1.wav

Binary file not shown.

BIN
Audio/Cooking/Basting/171336__brlproductions__gargle-then-spit 2.wav

Binary file not shown.

BIN
Audio/Cooking/Basting/2.wav

Binary file not shown.

BIN
Audio/Cooking/Basting/3.wav

Binary file not shown.

BIN
Audio/Cooking/Basting/4.wav

Binary file not shown.

BIN
Audio/Cooking/Fan/146251__ferdinger__suction-switched-off.wav

Binary file not shown.

BIN
Audio/Cooking/Fan/146251__ferdinger__suction-switched-on.aiff

Binary file not shown.

BIN
Audio/Cooking/Fan/146251__ferdinger__suction-switched-on.wav

Binary file not shown.

BIN
Audio/Cooking/Fan/146251__ferdinger__suction-switched-on1.wav

Binary file not shown.

BIN
Audio/Cooking/Oven Door/Door Slam Shut.wav

Binary file not shown.

BIN
Audio/Cooking/Oven Door/Oven Door Open.wav

Binary file not shown.

BIN
Audio/Cooking/Oven Door/Oven Door_Full_Close.mp3

Binary file not shown.

BIN
Audio/Cooking/Oven Door/Oven Door_Full_Close.wav

Binary file not shown.

BIN
Audio/Cooking/Oven Door/Oven_Door_Full_Open.mp3

Binary file not shown.

BIN
Audio/Cooking/Oven Door/Oven_Door_Full_Open.wav

Binary file not shown.

BIN
Audio/Cooking/Oven Door/Oven_Door_Peek_Close.mp3

Binary file not shown.

BIN
Audio/Cooking/Oven Door/Oven_Door_Peek_Close.wav

Binary file not shown.

BIN
Audio/Cooking/Oven Door/Oven_Door_Peek_Open.mp3

Binary file not shown.

BIN
Audio/Cooking/Oven Door/Oven_Door_Peek_Open.wav

Binary file not shown.

BIN
Audio/Cooking/Oven Door/RAW/Beeps and Toaster Oven.wav

Binary file not shown.

BIN
Audio/Cooking/Roasting/32371__walter-odington__frying-pan-chicken-and-onion.wav

Binary file not shown.

BIN
Audio/Events/Fire/189212__vurca__burning-fire.wav

Binary file not shown.

BIN
Audio/Events/Fire/87564__sgak__fire Fire Start Louder.wav

Binary file not shown.

BIN
Audio/Events/Fire/87564__sgak__fire Fire Start.wav

Binary file not shown.

BIN
Audio/Events/Fire/87564__sgak__fire Loop.wav

Binary file not shown.

BIN
Audio/Events/Fire/87564__sgak__fire.wav

Binary file not shown.

BIN
Audio/GUI/1.wav

Binary file not shown.

BIN
Audio/GUI/Click/63531__florian-reinke__click1.wav

Binary file not shown.

BIN
Audio/GUI/Click/63532__florian-reinke__click2.wav

Binary file not shown.

BIN
Audio/Store/Background Noises/131600__liam125__north-camp-railway-station-pa-announcements.wav

Binary file not shown.

BIN
Audio/Store/Background Noises/202029__hykenfreak__notification-chime.wav

Binary file not shown.

BIN
Audio/Store/Background Noises/72852__7by7__tannoy-announcement-jingle.wav

Binary file not shown.

BIN
Audio/Store/Background Noises/83915__cognito-perceptu__cash-register1.wav

Binary file not shown.

BIN
Audio/Store/Background Noises/83915__cognito-perceptu__cash-register2.wav

Binary file not shown.

BIN
Audio/Store/Background Sounds/72565__wrinex__supermarkt-ms.wav

Binary file not shown.

BIN
Audio/turkey_in_the_straw.mp3

Binary file not shown.

BIN
Main-Screen-MockupV11-24.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 617 KiB

BIN
Price List.xlsx

Binary file not shown.

67
README.md

@ -1,51 +1,32 @@
![GitHub Game Off Game Jam](https://f.cloud.github.com/assets/121322/1436486/25f88b78-4158-11e3-9b23-43596516362c.png) ![My image](https://raw.github.com/fernjager/game-off-2013/formula/Main-Screen-MockupV11-24.png)
## The Challenge ## Overview
You have the entire month of November to create a **web-based** game *loosely* based on the theme "change". It is another Thanksgiving holiday, a time of retrospect and blessings.
You have been invited over for dinner.
Wanting to make a good impression, you agree to cook the turkey…
What do we mean by **loosely** based on "change"? We literally mean, *loosely* based. Some examples might be a FPS where you throw the [loose change](http://www.merriam-webster.com/dictionary/loose%20change) in your pockets at the enemy or perhaps a puzzle game where you have to [change](http://www.merriam-webster.com/dictionary/change) form to overcome obstacles. ## Turkey Cooking Simulator Features:
* Real-time cooking action!
* Unparalleled turkey-based thermodynamics!
* Hours of gripping stories and drama!
* Accessorize your turkey with stuffing, frills, and other awesomeness!
* Day-night environmental cycle!
* High-definition stereo audio!
* Masterfully crafted scenes of an American household!
* Apply your culinary expertise to impress your family!
Your game. Your rules. You can participate either as an individual or as a team. You're encouraged to use open source libraries, frameworks, graphics, and sounds in your game.
## The Prizes ## Compatibility
* [Firefox](www.firefox.com) - Recommended Browser, Gstreamer required for sound on Mac OS
* [Chrome 22](https://www.google.com/intl/en/chrome/) - Full compatibility, recommended browser.
* [Safari 6.0.5](http://www.apple.com/safari/) - Some incompatibility with SVG
* [Internet Explorer 11](http://windows.microsoft.com/en-us/internet-explorer/download-ie) - Not recommended . Sound looping issues
We're giving away shiny new [iPad Airs](http://www.apple.com/ipad-air/) (16GB models) to our 5 lucky winners. Runners-up will receive a $100 credit for the [GitHub Shop](http://shop.github.com/), where they can grab some of our :octocat: shirts, hoodies, stickers, and more! ## Authors
All winners and runners-up will be showcased on our blog. * [Robert J. Chen](http://fernjager.net) - Programming
* [Benjamin Kwok](tengen1112@gmail.com) - Art
* [Scott R. Mobley](http://www.linkedin.com/in/mobleyscott) - Math and Dialogue
* Sheen Kao - Supreme Commissar Overlord MC
## Judging
We have a handful of judges who are eager to play your games!
* [Adam 'Atomic' Saltsman](https://twitter.com/adamatomic) - Game maker and dad, creator of Canabalt and Flixel.
* [Aleissia Laidacker](https://twitter.com/Aleissia) - Team Lead AI at Ubisoft.
* [David Czarnecki](http://twitter.com/CzarneckiD), Lead Engineer at Agora Games.
* [Matt Hackett](https://twitter.com/richtaur), Co-founder of Lost Decade Games.
* [Kyros Starr](https://twitter.com/bearwitched), Gaymer and Tech Writer at GitHub.
* [Lee Reilly](http://twitter.com/leereilly), Gamer Dad and Software Developer at GitHub.
* [Romana Ramzan](https://twitter.com/Manak/), Denki's Player Champion, Global Game Jam Director.
## The Rules
* To qualify for entry, you must fork the [github/game-off-2013](https://github.com/github/game-off-2013) repository to your individual or organization account. Not sure which account type would be best for you? Check out this handy [help article](https://help.github.com/articles/what-s-the-difference-between-user-and-organization-accounts), which explains the differences between the two types of accounts.
* All entries must be web-based, i.e. playable in a browser. HTML5, WebGL, Unity, Torque 3D, and Flash are all possible - just be sure the source is made available on your fork.
* You must be over the age of 13.
## Instructions
* If you don't already have a GitHub account, [sign up for a personal account now](https://github.com/signup/free) - it's free!
* Fork the [github/game-off-2013](https://github.com/github/game-off-2013) repository to your individual account (or to a [free organization account](https://github.com/organizations/new)).
* Be sure to follow [@github](https://twitter.com/github) on Twitter for updates.
* Make sure your code is pushed to the master branch of your forked repository before Dec 1st!
* Make sure you have a `README` file that includes a brief description of your game, what open source projects (if any) you used, and a screenshot.
* Your repository should have a brief description and the playable URL entered into the fields shown below (this will make our judging process easier):
![image](https://f.cloud.github.com/assets/121322/1436584/fd721126-415a-11e3-9f3a-e94262074573.png)
## Comments / Questions / Help
* New to Git, GitHub, and/or version control? Check out our [help documentation](https://help.github.com/) to get started!
* Questions about Git/GitHub? Please email [support@github.com](mailto:support@github.com) and be sure to include 'GitHub Game Off' in the subject.
* Questions specific to the GitHub Game Off? Please [create an issue](https://github.com/github/game-off-2013/issues/new). This will be the official FAQ.
* The official Twitter hashtag is [#ggo13](https://twitter.com/search/realtime?q=%23ggo13).

89
js/AlternativeModels.js

@ -0,0 +1,89 @@
function findClosest(value,array) {
closestDiff = null;
closestPosition = null;
for (var i=0;i<array.length;i++) {
diff = Math.abs(value-array[i])
if (diff<closestDiff || closestDiff == null) {
closestPosition=i;
closestDiff = diff;
}
}
return ([closestPosition,array[closestPosition]])
}
function biotSphereCoefficients (Biot) {
Bi = [0.01, 0.02, 0.04, 0.06, 0.08, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 40, 50, 100, 10000]
lambdaOne = [0.1730, 0.2445, 0.3450, 0.4217, 0.4860, 0.5423, 0.7593, 0.9208, 1.0528, 1.1656, 1.2644, 1.3525, 1.4320, 1.5044, 1.5708, 2.0288, 2.2889, 2.4556, 2.5704, 2.6537, 2.7165, 2.7654, 2.8044, 2.8363, 2.9857, 3.3072, 3.0632, 3.0788, 3.1102, 3.1416]
alphaOne = [ 1.0030, 1.0060, 1.0120, 1.0179, 1.0239, 1.0298, 1.0592, 1.0880, 1.1164, 1.1441, 1.1713, 1.1978, 1.2236, 1.2488, 1.2732, 1.4793, 1.6227, 1.7202, 1.7870, 1.8338, 1.8673, 1.8920, 1.9106, 1.9249, 1.9781, 1.9898, 1.9942, 1.9962, 1.9990, 2 ]
position = findClosest(Biot,Bi)[0]
return([lambdaOne[position], alphaOne[position]])
}
function lumpedCapacitance (outerRadius,radiusInner,tempInitial,tempInfini,heatConvectionTerm,t) {
volume = (4/3)*Math.PI*Math.pow(outerRadius,3) - (4/3)*Math.PI*Math.pow(radiusInner,3); //3D Sphere
surfaceArea = 4*Math.PI*Math.pow(outerRadius,2); //3D Sphere
mass = density * volume;
charLength = volume/surfaceArea ;
biotNum = heatConvectionTerm * charLength/thermalConduct
console.log("The Biot Value is " + biotNum)
b=(heatConvectionTerm)/(density*charLength*cp)
console.log("The time constant b is "+ b)
tempAtTime = Math.exp(-b*t)*(tempInitial-tempInfini)+tempInfini;
console.log("The Temperature at time " + t +" seconds is " + tempAtTime)
qDot = -1*heatConvectionTerm*surfaceArea*(tempAtTime-tempInfini) //Heat Transfer Rate Useful for water Loss
console.log("The Heat Flux is " + qDot )
return([tempAtTime,qDot])
}
function transientSphereOneTerm (rPosition,rTotal,tempInitial,tempInfini,t) {
alpha = thermalConduct/(density*cp)
console.log("Alpha is " + alpha)
Fourier = (alpha*t)/Math.pow(rTotal,2)
console.log("Fourier is " + Fourier)
biotNum = heatConvection * rTotal/thermalConduct
console.log("The Biot Value is " + biotNum)
temp=biotSphereCoefficients(biotNum)
lambdaOne=temp[0];
alphaOne=temp[1];
console.log("lambda1 is " + lambdaOne)
console.log("A1 is " + alphaOne)
//This is only valid for Fourier greater than 0.2
sinPortion= Math.sin(lambdaOne*rPosition/rTotal)/(lambdaOne*rPosition/rTotal);
expotentialPortion = alphaOne*(1/Math.exp(Math.pow(lambdaOne,2)*Fourier))
tempAtTimeAndRadius=(sinPortion*expotentialPortion*(tempInitial-tempInfini))+tempInfini
console.log("The Temperature at radius " + rPosition + " m and time " + t + " seconds is " + tempAtTimeAndRadius + " C or " + celsiusToFarenheit(tempAtTimeAndRadius) + " F");
}
function lumpedCapacitanceMethod (outerRadius,radiusInner,tempInitial,tempInfini, t) {
volume = (4/3)*Math.PI*Math.pow(outerRadius,3) - (4/3)*Math.PI*Math.pow(radiusInner,3); //3D Sphere
surfaceArea = 4*Math.PI*Math.pow(outerRadius,2); //3D Sphere
mass = density * volume;
charLength = volume/surfaceArea ;
biotNum = heatConvection * charLength/thermalConduct
console.log("The Biot Value is " + biotNum)
b=(heatConvection)/(density*charLength*cp)
console.log("The time constant b is "+ b)
tempAtTime = Math.exp(-b*t)*(tempInitial-tempInfini)+tempInfini;
console.log("The Temperature at time " + t +" seconds is " + tempAtTime)
Qdot = -1*heatConvection*surfaceArea*(tempAtTime-tempInfini) //Heat Transfer Rate Useful for water Loss
console.log("The Heat Flux is " + Qdot )
return(tempAtTime)
}
function findAllRoots (Biot) {
limit = 50; //Terms to Compute too
storage = [];
for (var k=0; k<=limit; k++) {
minK = (k+0.5)*Math.PI;
maxK = (k+1)*Math.PI;
answer = bisectionMethod(minK,maxK,Biot);
if (answer !=undefined) {
storage.push(answer);
}
}
//console.log(storage)
return(storage)
}

263
js/CookingFormula.js

@ -0,0 +1,263 @@
//Useful Websites
// http://math.stackexchange.com/questions/406082/numerical-method-to-solve-a-trigonometric-cotangent-function-transient-heat
// http://web.cecs.pdx.edu/~gerry/epub/pdf/transientConductionSphere.pdf
// http://web.cecs.pdx.edu/~gerry/epub/
//http://highered.mcgraw-hill.com/sites/dl/free/0073129305/314124/cen29305_ch04.pdf
//http://www.nt.ntnu.no/users/skoge/prost/proceedings/aiche-2005/topical/pdffiles/T9/papers/554a.pdf
//http://www.rohanliston.com/portfolio/just-for-fun?id=23
//Global Variables for Turkey
density = 1050; // kg/m3 Assuming Density of Water 1000 kg/m3
cp = 2000 // 2810 J/kg K for Turkey. Extra is to semi-account for water evaporation energy
heatConvection = 9; // W/m2 K Some Reasonable estimate for natural Convection. Change as needed. 5-25
thermalConduct = 0.412 // W/m K // Chicken
globalTime = 0;
function celsiusToFarenheit(celsius) {
farenheit = (celsius*(9/5)) + 32;
return(farenheit)
}
function farenheitToCelsius (farenheit) {
celsius = (farenheit*(9/5)) + 32;
return(celsius)
}
function poundsToKilograms(pounds) {
kilograms = (pounds * 0.453592);
return(kilograms)
}
function calculateRadius(weight) {
//Using Ratios for a rectangular Box Turkey
ratioLvG=1.4; //1.4, Turkey length vs shoulder girth
ratioLvH=2; //2, Turkey length vs height from resting position
length = Math.pow(weight/((1/ratioLvG)*(1/ratioLvH)*density),(1/3))
depth = 1/(ratioLvG /length);
height = 1/(ratioLvH /length);
simpleRadius = length/2; //Doesn't take into account equal Volume
rectangleVolume = depth*height*length; //m^3 Multiple by 1/3 to account for triangular shape and empty Space
complexRadius = Math.pow(rectangleVolume/((4/3)*Math.PI), 1/3); //Volume of 3D Box = 3D Sphere
console.log("Simple Radius " + simpleRadius + " Meters")
console.log("Complex Radius " + complexRadius + " Meters")
return(complexRadius)
}
function findAllRoots(min,max,splitsNum,Biot) {
var step = ( max - min ) / ( splitsNum - 1 );
var storage = [];
for (var i = step; i < max; i=i+step ) {
negativeTest = lambdaFormula(i-step, Biot)*lambdaFormula(i, Biot);
if (negativeTest <= 0) {
answer = bisectionMethod(i-step,i,Biot);
if (answer !=undefined) {
storage.push(answer);
}
}
else {
//console.log("No Bracketed Root " + negativeTest)
}
}
return(storage)
}
function bisectionMethod(min,max,Biot) {
errorTolerance = (1/Math.pow(10,8))
result = Infinity // some large value to ensure the calculation goes through.
negativeTest =lambdaFormula(min, Biot)*lambdaFormula(max, Biot)
if (negativeTest <=0 ) {
var antiFreeze=0;
while (Math.abs(result) > errorTolerance && antiFreeze<=500) { //The greater the antiFreeze, the more wasted cycles around a singularity
lambdaN = (min+max)/2
result=lambdaFormula(lambdaN, Biot)
if (Math.abs(result) <= errorTolerance && result<=errorTolerance) {
return (lambdaN); //At Root
}
else if ((lambdaFormula(min, Biot)*lambdaFormula(lambdaN, Biot))>=0) {
min=lambdaN;
}
else if ((lambdaFormula(max, Biot)*lambdaFormula(lambdaN, Biot))>=0) {
max=lambdaN;
}
antiFreeze++
}
}
}
function lambdaFormula(lambdaN, Biot) {
result = 1-lambdaN*(1/Math.tan(lambdaN))-Biot;
return(result)
}
function oven() {
this.tempInfini=20; //C
this.setTemp = 20;
this.steadyTemp = 20;
this.steadyTimer = 0;
var proportional = 0.004; // This value is arbitrary to how fast you want the temperatures to converge. (Or oscillate, which could be realistic as well)
var errorTolerance = 10; //Stove is accurate to 25 degree Celcius Should hopefully oscillate below that value.
this.changeTemp = function(setTemp) {
this.setTemp = setTemp;
}
this.equalizeTemp = function() { // Equalize Temp will need to be sent each time iteration
var error = Math.abs(this.setTemp-this.tempInfini);
if (this.setTemp>this.tempInfini) {
this.tempInfini = this.tempInfini + error*proportional;
}
else if (this.setTemp<this.tempInfini) {
this.tempInfini = this.tempInfini - error*proportional;
}
if (error>errorTolerance) {
return (true) //Need to run the Heat Calculations again next cycle
}
else {
this.steadyTemp = this.tempInfini;
}
}
}
function layerModel(name,radiusPercentage) {
this.name = name;
this.radiusPercent=radiusPercentage;
this.initialTemp = 20;
this.waterLost = 0;
this.finalTemperature = 20;
}
function turkeyModel(weight) {
this.totalRadius = calculateRadius(weight)
this.skin = new layerModel("Skin",0.85)
this.body = new layerModel("Body",0.45)
this.core = new layerModel("Core",0.01)
this.cookCondition = function(cookValue) {
var multiplier = 1;
if (cookValue>=multiplier*250000) {
return("House Fire")
}
else if(cookValue>=multiplier*150000) {
return("Charcoal")
}
else if (cookValue>=multiplier*80000) {
return("Dry")
}
else if (cookValue>=multiplier*18000) {
return("Cooked")
}
else if (cookValue>=multiplier*5000) {
return("Undercooked")
}
else {
return("Raw")
}
}
this.resetLayerTemps = function () {
this.skin.initialTemp = this.skin.finalTemperature;
this.body.initialTemp = this.body.finalTemperature;
this.core.initialTemp = this.core.finalTemperature;
}
this.updateLayerTemps = function() {
//Temperature Calculations
this.skin.finalTemperature = transientSphereSeries (this.skin.radiusPercent*this.totalRadius,this.totalRadius,this.skin.initialTemp,ovenObject.steadyTemp,globalTime)
this.body.finalTemperature = transientSphereSeries (this.body.radiusPercent*this.totalRadius,this.totalRadius,this.body.initialTemp,ovenObject.steadyTemp,globalTime)
this.core.finalTemperature = transientSphereSeries (this.core.radiusPercent*this.totalRadius,this.totalRadius,this.core.initialTemp,ovenObject.steadyTemp,globalTime)
//Water Loss Calculations
this.skin.waterLost = this.skin.waterLost + waterLoss(this.skin.finalTemperature)
this.body.waterLost = this.body.waterLost + waterLoss(this.body.finalTemperature)
this.core.waterLost = this.core.waterLost + waterLoss(this.core.finalTemperature)
console.log("Skin: "+ this.skin.waterLost + " " + turkey.cookCondition(this.skin.waterLost));
console.log("Body: "+ this.body.waterLost + " " + turkey.cookCondition(this.body.waterLost));
console.log("Core: "+ this.core.waterLost + " " + turkey.cookCondition(this.core.waterLost));
}
}
function sphereVolume (radius) {
return((4/3)*Math.PI*Math.pow(radius,3))
}
function sphereSurfaceArea(radius) {
return (4*Math.PI*Math.pow(radius,2))
}
function waterLoss(temperature) {
return (Math.pow(10,(temperature-20)/80)-1)
}
var oldBiot=null;
function transientSphereSeries (rPosition,rTotal,tempInitial,tempInfini,t) {
var min = 0;
var max = 10000; // This are for setting Lambda boundries and nothing else
//thermalConduct = ((tempInitial-20)*(0.13/60)) + 0.32;
var sum=0;
var alpha = thermalConduct/(density*cp)
//console.log("Alpha is " + alpha)
var Fourier = (alpha*t)/Math.pow(rTotal,2)
//console.log("Fourier is " + Fourier)
var biotNum = heatConvection * rTotal/thermalConduct
if (biotNum != oldBiot) {
console.log("Recalculating Lambda Terms")
lambdaTerms = findAllRoots(min,max,max*Math.PI*10,biotNum)
oldBiot = biotNum;
}
//console.log("The Biot Value is " + biotNum)
for (var i = 0; i<lambdaTerms.length; i++) {
lambdaN = lambdaTerms[i]
sinPortion= Math.sin(lambdaN*rPosition/rTotal)/(lambdaN*rPosition/rTotal);
exponentialPortion = (1/Math.exp(Math.pow(lambdaN,2)*Fourier))
frontCoefficientPortion = 4*(Math.sin(lambdaN)-(lambdaN*Math.cos(lambdaN)))/ (2*lambdaN-Math.sin(2*lambdaN))
sum = frontCoefficientPortion*exponentialPortion*sinPortion + sum
}
tempAtTimeAndRadius=(sum*(tempInitial-tempInfini))+tempInfini
console.log("The Temperature at radius " + rPosition + " m and time " + t/60/60 + " hours is " + tempAtTimeAndRadius + " C or " + celsiusToFarenheit(tempAtTimeAndRadius) + " F");
return(tempAtTimeAndRadius)
}
//Running the Program Stuff
ovenObject = new oven ();
turkey = new turkeyModel(7.257);
setInterval(function(){time()},1000);
totalCookTime = 0;
scale = 1
function time() {
console.clear()
var equalized = ovenObject.equalizeTemp()
if (ovenObject.steadyTimer>=80*scale && equalized) {
ovenObject.steadyTimer = 0;
ovenObject.steadyTemp = ovenObject.tempInfini
turkey.resetLayerTemps();
globalTime = 0; //Reset the model's time calculation if there are major changes in the tolerance of the temperature
}
else {
globalTime = globalTime + scale;
ovenObject.steadyTimer = ovenObject.steadyTimer + scale;
totalCookTime = totalCookTime + scale;
}
console.log(ovenObject.tempInfini)
console.log(ovenObject.steadyTemp)
console.log(ovenObject.steadyTimer)
console.log(totalCookTime/60/60 +" hours")
turkey.updateLayerTemps();
}

289
js/Sheen's Model - WIP/model.js

@ -0,0 +1,289 @@
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; i<this.splitsNum ; i++ ) {
this.pointRadius.push(step*i+this.deltar);
this.globTemp.push(20+step*i); //Starts at 20 C for initilizating
}
};
this.initializePoints()
}
function OvenModel( turkeyWeight, gameState ) {
var that = this;
this.tempInfini=20; //C
this.setTemp = 20;
this.globalTime = 0;
var turkey = new TurkeyModel(turkeyWeight, this );
var proportional = 0.004; // This value is arbitrary to how fast you want the temperatures to converge. (Or oscillate, which could be realistic as well)
var errorTolerance = 10; //Stove is accurate to 1 degree Celcius Should hopefully oscillate below that value.
// Equalize temp will need to be sent each time iteration
this.equalizeTemp= function(){
var error = Math.abs(this.setTemp-this.tempInfini);
if( this.setTemp>this.tempInfini ){
this.tempInfini = this.tempInfini + error*proportional;
}
else if( this.setTemp<this.tempInfini ){
this.tempInfini = this.tempInfini - error*proportional;
}
if( error>errorTolerance ) {
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<splitsNum; k++){
if (k==0) {
dTdr.push((globTemp[1] - globTemp[0])/deltar) }
else if (k==splitsNum-1) {
dTdr.push((globTemp[splitsNum-1] - globTemp[splitsNum-2])/deltar)}
else {
dTdr.push((globTemp[k+1] - globTemp[k-1])/(2*deltar))}
}
dTdr[splitsNum-1] = heatConvection*(tempInfinity-globTemp[splitsNum-1])/thermalConduct
var parenthesis = []
for (var k=0; k<splitsNum; k++){
parenthesis.push(dTdr[k]*Math.pow(pointRadius[k],2))
}
dPdr = []
for (var k=0; k<splitsNum; k++){
if (k==0) {
dPdr.push((parenthesis[1] - parenthesis[0])/deltar) }
else if (k==splitsNum-1) {
dPdr.push((parenthesis[splitsNum-1] - parenthesis[splitsNum-2])/deltar)}
else {
dPdr.push((parenthesis[k+1] - parenthesis[k-1])/(2*deltar))}
}
for (var k=0; k<splitsNum; k++){
globTemp[k]=alpha*dPdr[k]/Math.pow(pointRadius[k],2)*deltat + globTemp[k] //dTdr * deltaT in one loop
}
//dTdt(1)=dTdt(1)/2;
}
console.log("dPdr" + dPdr)
return(globTemp)
},
/* Utility Functions */
C2F: function( celsius ){
return ( (celsius*(9/5)) + 32 );
},
F2C: function( farenheit ) {
return ( (farenheit-32) *(5/9) );
},
lbs2kgs: function(pounds){
return pounds * 0.453592
},
randRange: function(min, max){
return Math.floor(Math.random()*(max-min+1))+min;
},
cookCondition: function(cookValue,volume){
var multiplier = 1;
if (cookValue>=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);
*/

8
js/Turkey.html

@ -0,0 +1,8 @@
<!DOCTYPE html>
<html>
<head>
<title>Turkey Formulas</title>
<script src=CookingFormula.js></script>
</head>
</body>
</html>
Loading…
Cancel
Save