JSFiddle - React, Tailwind, and code Playground

by Gwyn Milcote

HTML

Egg incubation simulator.

<!-- Visible only in test mode, with fake eggs. -->

<div id='inc_controls' style='display:none;'>
    Breed: <select id='inc_test_breed'>
        <option value='1'>Average</option>
        <option value='2'>Mountain</option>
        <option value='3'>Volcano</option>
    </select><br>
    <button id='inc_advance'>Advance 1 hour</button>  |  <button id='inc_reset'>Reset</button>
</div>

<!-- Visible for special eggs, or tester users. -->

<div id='inc_unlocked' class='spaced flex space_between' style='display:none;'>
    <div class='info_panel quarter'>
        Health: <b><span id='inc_status_eggHealth'>?</span>%</b>
    </div>
    <div class='info_panel quarter'>
        Sex: <b><span id='inc_status_sex'>?</span></b>
    </div>
    <div class='info_panel quarter'>
        Dev points: <b><span id='inc_status_devPoints'>?</span></b><br>
    </div>
    <div class='info_panel quarter'>
        Heat points: <b><span id='inc_status_heatPoints'>?</span></b><br>
    </div>
    <div class='info_panel quarter'>
        Cold points: <b><span id='inc_status_coldPoints'>?</span></b><br>
    </div>
</div>

<div id='inc_status_panel' class='spaced flex space_between'>
    <div class='info_panel quarter'>
        Name: <b><span id='inc_status_name'>?</span></b><br>
    </div>
    <div class='info_panel quarter'>
        Breed: <b><span id='inc_status_breed'>?</span></b><br>
    </div>
    <div class='info_panel quarter'>
        Current hour: <b><span id='inc_status_devHours'>?</span></b><br>
    </div>
    <div class='info_panel quarter'>
        Last heat: <b><span id='inc_status_lastHeat'>?</span></b><br>
    </div>
    <div class='info_panel quarter'>
        Current heat: <b><span id='inc_status_currentHeat'>?</span></b><br>
    </div>
</div>

<p><div id='inc_egg_image'>[img]</div></p>

<div id='heat_options'>
    <button class='heat_option' id='heat_1' data-heat='1'>Freeze</button>
    <button class='heat_option' id='heat_2'...

CSS

* {box-sizing: border-box;}

#spoilers, #guide {
    display: none;
}

#heat_options {
    width: 100%;
    max-width: 500px;
    margin: 20px auto;
    display: flex;
    justify-content: space-between;
}

.heat_option {
    cursor: pointer;
    margin: 5px;
    padding: 10px 20px;
    background-color: #e7e7e7;
    border: 1px solid grey;
}

.heat_option:hover {
    opacity: 0.8;
    box-shadow: 0px 2px 5px 2px rgba(0, 0, 0, 0.2);
}

.current_heat {
    box-shadow: 0px 2px 5px 2px rgba(0, 0, 0, 0.4);
}

/* Styles for the 5 heat buttons. */
#heat_1 {
    background-color: skyblue;
}
#heat_2 {
    background-color: lightblue;
}
#heat_3 {
    background-color: lightgreen;
}
#heat_4 {
    background-color: orange;
}
#heat_5 {
    background-color: orangered;
}


.spaced {
    margin: 10px auto;
}

.space_between {
    justify-content: space-between;
}
.info_panel {
    border: 1px solid grey;
    padding: 10px;
    margin: 0px 5px;
}

.flex {
    display: flex;
}
.half {
    width: 50%;
}
.quarter {
    width: 25%;
}

JavaScript

/*
let egg = {
    id: 178,
    name: "Topaz",
    sex: 1,
    breed: 1,
    health: 100,
    devPoints: 0,
    devHours: 0,
    lastHeat: 3,
    currentHeat: 3,
    coldPoints: 0,
    heatPoints: 0,
    geno: {},
    mods: {}
};
*/
class Util {

    static randomGenotype(){
        return {
            geno: {a1: "A+", a2: "a"},
            mods: {sooty: 0, cp: 0, mask: 2, shadow: 0, snow: 0}
        };
    }
    
    static getBreedName(n){return "aa";}
    static getSexName(n){return "mf";}

}

function RN(n1, n2){
    if(n1 == n2){ return n1; }
    var min = n1; var max = n2;
    if(n1 > n2){ min = n2; max = n1; }
    return Math.floor(Math.random()*(max-min+1)+min);
}

function RA(array){
    return array[Math.floor(Math.random() * array.length)];
}

/*
* Incubation defaults:
* 20 damage for Cool/Warm, 50 damage for Freeze/Roast.
* 1-5 dev points, matches temp.
* cT, hT = tolerance for colder/hotter temps.
* cD, hD = dev points given in colder/hotter temps.
*/

const breeds = [
    {name: "Avg", cT: 6, hT: 5, cD: 5, hD: 8},
    {name: "Mtn", cT: 6, hT: 5, cD: 5, hD: 8},
    {name: "Volcano", cT: 6, hT: 5, cD: 5, hD: 8},
    {name: "Axia", cT: 6, hT: 5, cD: 5, hD: 8}
];

/*
* A single egg must be loaded at a time.
* Genotype object is needed only for image gen.
* Modifier numbers are what's actually edited.
*/
class Incubation {

    constructor(egg = false){
        if(!egg){
            this.testMode = true;
            this.showTestControls();
            this.showUnlockedInfo();
            this.reset();
        }else{
            this.setEgg(egg);
            this.testMode = false;
            // Users can unlock full info.
            // Testers also need it enabled.
            if(this.unlocked){
                this.showUnlockedInfo();
            }
        }
    }
    
    /*
    * Load an egg object, that was fetched from DB.
    * If viewing an individual egg's profile page,
    * this data was in JSON tags.
    */
    setEgg(e){
        let vars =...