code:
import { round } from "../../common/math";
import { useBackend, useLocalState } from "../backend";
import { Flex, Stack, Section, LabeledList, ProgressBar, Tabs, Box, BlockQuote, Collapsible, AnimatedNumber } from '../components';
import { Window } from "../layouts";

export const HealthAnalyzer = (props, context) => {
  const { act, data } = useBackend(context);
  const [tabIndex, setTabIndex] = useLocalState(context, 'tabIndex', 'Overall');
  const {
    patient,
  } = data;

  return (
    <Window
      title={`Analyzing ${patient}`}
      width={850}
      height={700}>
      <Window.Content
        scrollable>
        <Tabs
          vertical={false}
          fluid={false}
          textAlign={'center'}>
          <Tabs.Tab
            key={'Overall'}
            selected={tabIndex === 'Overall'}
            onClick={() => setTabIndex('Overall')}>
            Overall
          </Tabs.Tab>
          <Tabs.Tab
            key={'Bodyparts'}
            selected={tabIndex === 'Bodyparts'}
            onClick={() => setTabIndex('Bodyparts')}>
            Bodyparts
          </Tabs.Tab>
          <Tabs.Tab
            key={'Organs'}
            selected={tabIndex === 'Organs'}
            onClick={() => setTabIndex('Organs')}>
            Organs
          </Tabs.Tab>
          <Tabs.Tab
            key={'Diseases'}
            selected={tabIndex === 'Diseases'}
            onClick={() => setTabIndex('Diseases')}>
            Diseases
          </Tabs.Tab>
          <Tabs.Tab
            key={'Psyche'}
            selected={tabIndex === 'Psyche'}
            onClick={() => setTabIndex('Psyche')}>
            Psyche
          </Tabs.Tab>
          <Tabs.Tab
            key={'Chemicals'}
            selected={tabIndex === 'Chemicals'}
            onClick={() => setTabIndex('Chemicals')}>
            Chemicals
          </Tabs.Tab>
        </Tabs>
        {tabIndex === 'Overall' && (
          <OverallScan />
        )}
        {tabIndex === 'Bodyparts' && (
          <BodypartScan />
        )}
        {tabIndex === 'Organs' && (
          <OrganScan />
        )}
        {tabIndex === 'Diseases' && (
          <DiseaseScan />
        )}
        {tabIndex === 'Psyche' && (
          <PsychScan />
        )}
        {tabIndex === 'Chemicals' && (
          <ChemScan />
        )}
      </Window.Content>
    </Window>
  );
};

const OverallScan = (props, context) => {
  const { data } = useBackend(context);
  const {
    advanced,
    species,
    status,
    anencephalic,
    catatonic,
    brain_activity,
    overall_damage,
    oxyloss,
    toxloss,
    cloneloss,
    fireloss,
    bruteloss,
    staminaloss,
    traumatic_shock,
    shock_stage,
    husked,
    disfigured,
    radiation,
    hallucinating,
    cardiac_arrest,
    genetic_stability,
    core_temperature,
    body_temperature,
    timeofdeath,
    blood_name,
    blood_type,
    bleed_rate,
    pulse,
    normal_blood_volume,
    blood_volume,
    blood_volume_perc,
    blood_circulation,
    blood_circulation_perc,
    blood_oxygenation,
    blood_oxygenation_perc,
    icon64,
    funnyquote,
  } = data;

  return (
    <Stack fill>
      <Stack.Item width="65%">

          {funnyquote}

        <Section title={`Blood`}>
          <LabeledList>
            <LabeledList.Item label={`Blood Reagent`}>
              {blood_name}
            </LabeledList.Item>
            <LabeledList.Item label={`Blood Type`}>
              {blood_type}
            </LabeledList.Item>
            <LabeledList.Item label={`Ideal Blood Volume`}>
              <AnimatedNumber value={normal_blood_volume} />cl
            </LabeledList.Item>
            <LabeledList.Item
              label={`Blood Volume`}>
              <ProgressBar
                value={blood_volume_perc/100}
                color={`bad`}>
                <AnimatedNumber value={blood_volume} />cl
                / <AnimatedNumber value={blood_volume_perc} />%
              </ProgressBar>
            </LabeledList.Item>
            <LabeledList.Item
              label={`Blood Circulation`}>
              <ProgressBar
                value={blood_circulation_perc/100}
                color={`bad`}>
                <AnimatedNumber value={blood_circulation} />cl
                / <AnimatedNumber value={blood_circulation_perc} />%
              </ProgressBar>
            </LabeledList.Item>
            <LabeledList.Item
              label={`Blood Oxygenation`}>
              <ProgressBar
                value={blood_oxygenation_perc/100}
                color={`bad`}>
                <AnimatedNumber value={blood_oxygenation} />cl
                / <AnimatedNumber value={blood_oxygenation_perc} />%
              </ProgressBar>
            </LabeledList.Item>
            <LabeledList.Item
              label={`Bleed Rate`}>
              <ProgressBar
                value={advanced ? bleed_rate/10 : (bleed_rate ? 1 : 0)}
                color={"bad"}>
                {advanced
                  ? <AnimatedNumber value={bleed_rate} />
                  : bleed_rate ? "Bleeding" : "Not Bleeding"}
                {advanced
                  ? `cl/s` : null}
              </ProgressBar>
            </LabeledList.Item>
            <LabeledList.Item label={`Pulse`}>
              {pulse} bpm
            </LabeledList.Item>
          </LabeledList>

        <Section title={`Damage`}>
          <LabeledList>
            <LabeledList.Item label={`Brain Activity`}>
              <ProgressBar
                value={brain_activity/100}
                color={brain_activity >= 50 ? "good" : "bad"}>
                <AnimatedNumber value={brain_activity} />%
              </ProgressBar>
            </LabeledList.Item>
            <LabeledList.Item label={`Genetic Stability`}>
              <ProgressBar
                value={genetic_stability/100}
                color={genetic_stability >= 50 ? "good" : "bad"}>
                <AnimatedNumber value={genetic_stability} />%
              </ProgressBar>
            </LabeledList.Item>
            <LabeledList.Item label={`Radiation Level`}>
              <ProgressBar
                value={advanced ? `${radiation/100}` : (radiation ? 1 : 0)}
                color={radiation ? "bad" : "good"}>
                {advanced
                  ? <AnimatedNumber value={radiation} />
                  : radiation ? "Detected" : "Undetected"}
                {advanced
                  ? `%` : null}
              </ProgressBar>
            </LabeledList.Item>
            <LabeledList.Divider />
            <LabeledList.Item label={`Accumulated Damage`}>
              <ProgressBar
                value={overall_damage/100}
                color="bad">
                <AnimatedNumber value={overall_damage} />
              </ProgressBar>
            </LabeledList.Item>
            <LabeledList.Item label={`Brute Damage`}>
              <ProgressBar
                value={bruteloss/100}
                color="bad">
                <AnimatedNumber value={bruteloss} />
              </ProgressBar>
            </LabeledList.Item>
            <LabeledList.Item label={`Burn Damage`}>
              <ProgressBar
                value={fireloss/100}
                color="bad">
                <AnimatedNumber value={fireloss} />
              </ProgressBar>
            </LabeledList.Item>
            <LabeledList.Item label={`Oxygen Damage`}>
              <ProgressBar
                value={oxyloss/100}
                color="bad">
                <AnimatedNumber value={oxyloss} />
              </ProgressBar>
            </LabeledList.Item>
            <LabeledList.Item label={`Cellular Damage`}>
              <ProgressBar
                value={advanced ? cloneloss/100 : (cloneloss ? 1 : 0)}
                color="bad">
                {advanced
                  ? <AnimatedNumber value={cloneloss} />
                  : cloneloss ? "Detected" : "Undetected"}
              </ProgressBar>
            </LabeledList.Item>
            <LabeledList.Item label={`Toxin Damage`}>
              <ProgressBar
                value={toxloss/100}
                color="bad">
                <AnimatedNumber value={toxloss} />
              </ProgressBar>
            </LabeledList.Item>
            <LabeledList.Item label={`Stamina Loss`}>
              <ProgressBar
                value={advanced ? staminaloss/100 : (staminaloss ? 1 : 0)}
                color="bad">
                {advanced
                  ? <AnimatedNumber value={staminaloss} />
                  : staminaloss ? "Detected" : "Undetected"}
              </ProgressBar>
            </LabeledList.Item>
            <LabeledList.Item label={`Pain`}>
              <ProgressBar
                value={traumatic_shock/100}
                color="bad">
                <AnimatedNumber value={traumatic_shock} />
              </ProgressBar>
            </LabeledList.Item>
            <LabeledList.Item label={`Shock`}>
              <ProgressBar
                value={shock_stage/100}
                color="bad">
                <AnimatedNumber value={shock_stage} />
              </ProgressBar>
            </LabeledList.Item>
          </LabeledList>

      </Stack.Item>
      <Stack.Item width="35%">
        <Box
          my={3.5}
        />
        {(icon64 ? true : false) && (
          <Section
            textAlign={`center`}
            title={species}>
            <Box
              as="img"
              m={0}
              height="100%"
              width="100%"
              src={`data:image/jpeg;base64,${icon64}`}
              style={{
                '-ms-interpolation-mode': 'nearest-neighbor',
              }} />

        )}
        <Section title={`Status`}>
          <Box
            color={status === 'Conscious' ? "good" : (status === "Dead" ? "#e2c1ff" : "bad")}>
            {status}
          </Box>
          {(anencephalic ? true : false) && (
            <Box color="bad">
              {anencephalic}
            </Box>
          )}
          {(cardiac_arrest ? true : false) && (
            <Box color="bad">
              {cardiac_arrest}
            </Box>
          )}
          {(catatonic ? true : false) && (
            <Box color="#e2c1ff">
              {catatonic}
            </Box>
          )}
          {(husked ? true : false) && (
            <Box color="bad">
              {husked}
            </Box>
          )}
          {(disfigured ? true : false) && (
            <Box color="bad">
              {disfigured}
            </Box>
          )}
          {(hallucinating ? true : false) && (
            <Box color="#e2c1ff">
              {hallucinating}
            </Box>
          )}
          {(status === "Dead" && timeofdeath ? true : false) && (
            <Box color="#e2c1ff">
              {`Time of death: ${timeofdeath}`}
            </Box>
          )}

        <Section title={`Temperature`}>
          <LabeledList>
            <LabeledList.Item label="Body Temperature">
              <ProgressBar
                value={1}>
                <AnimatedNumber value={round(body_temperature, 10)} />K
                / <AnimatedNumber value={round(body_temperature-273, 10)} />°C
              </ProgressBar>
            </LabeledList.Item>
            <LabeledList.Item label="Core Temperature">
              <ProgressBar
                value={1}>
                <AnimatedNumber value={round(core_temperature, 10)} />K
                / <AnimatedNumber value={round(core_temperature-273, 10)} />°C
              </ProgressBar>
            </LabeledList.Item>
          </LabeledList>

      </Stack.Item>
    </Stack>
  );
};

const BodypartScan = (props, context) => {
  const { data } = useBackend(context);
  const {
    advanced,
    bodyparts = [],
  } = data;
  const [bodypartTabIndex, setBodypartTabIndex] = useLocalState(context, 'organTabIndex', bodyparts[0].zone);
  const activeZone = bodyparts.find(bodyzone => {
    return bodyzone.zone === bodypartTabIndex;
  });

  return (
    <Flex>
      <Flex.Item>
        <Tabs
          fill
          vertical>
          {bodyparts.map(bodypart => (
            <Tabs.Tab
              key={bodypart.zone}
              selected={bodypartTabIndex === bodypart.zone}
              onClick={() => setBodypartTabIndex(bodypart.zone)}>
              {bodypart.zone}
            </Tabs.Tab>
          ))}
        </Tabs>
      </Flex.Item>
      <Flex.Item>

          <LabeledList>
            {(activeZone.name === "Missing") && (
              <LabeledList.Item
                color={"bad"}
                label={`Status`}>
                {activeZone.name}
              </LabeledList.Item>
            )}
            {(activeZone.name !== "Missing") && (
              <LabeledList.Item
                label={`Name`}>
                {activeZone.name}
              </LabeledList.Item>
            )}
            {(activeZone.name !== "Missing") && (
              <LabeledList.Item
                label={`Status`}>
                {activeZone.status}
              </LabeledList.Item>
            )}
            {(activeZone.name !== "Missing") && (
              <LabeledList.Item
                label={`Maximum Damage`}>
                {activeZone.max_damage}
              </LabeledList.Item>
            )}
            {(activeZone.name !== "Missing") && (
              <LabeledList.Item
                label={`Overall Damage`}>
                <ProgressBar
                  value={activeZone.overall_damage/activeZone.max_damage}
                  color={`bad`}>
                  <AnimatedNumber value={activeZone.overall_damage} />
                </ProgressBar>
              </LabeledList.Item>
            )}
            {(activeZone.name !== "Missing") && (
              <LabeledList.Item
                label={`Brute Damage`}>
                <ProgressBar
                  value={activeZone.bruteloss/activeZone.max_damage}
                  color={`bad`}>
                  <AnimatedNumber value={activeZone.bruteloss} />
                </ProgressBar>
              </LabeledList.Item>
            )}
            {(activeZone.name !== "Missing") && (
              <LabeledList.Item
                label={`Burn Damage`}>
                <ProgressBar
                  value={activeZone.fireloss/activeZone.max_damage}
                  color={`bad`}>
                  <AnimatedNumber value={activeZone.fireloss} />
                </ProgressBar>
              </LabeledList.Item>
            )}
            {(activeZone.name !== "Missing") && (
              <LabeledList.Item
                label={`Stamina Damage`}>
                {advanced && (
                  <ProgressBar
                    value={activeZone.staminaloss/activeZone.max_stam_damage}
                    color={`bad`}>
                    <AnimatedNumber value={activeZone.staminaloss} />
                  </ProgressBar>
                ) || (
                  <ProgressBar
                    value={activeZone.staminaloss ? 1 : 0}
                    color={`bad`}>
                    {activeZone.staminaloss ? "Detected" : "Undetected"}
                  </ProgressBar>
                )}
              </LabeledList.Item>
            )}
            {(activeZone.name !== "Missing") && (
              <LabeledList.Item
                label={`Pain`}>
                <ProgressBar
                  value={activeZone.traumatic_shock/activeZone.max_pain}
                  color={`bad`}>
                  <AnimatedNumber value={activeZone.traumatic_shock} />
                </ProgressBar>
              </LabeledList.Item>
            )}
            {(activeZone.name !== "Missing") && (
              <LabeledList.Item
                label={`Infection Level`}>
                {advanced && (
                  <ProgressBar
                    value={activeZone.germ_level/100}
                    color={`bad`}>
                    <AnimatedNumber value={activeZone.germ_level} />%
                  </ProgressBar>
                ) || (
                  <ProgressBar
                    value={activeZone.germ_level ? 1 : 0}
                    color={`bad`}>
                    {activeZone.germ_level ? "Infection" : "No Infection"}
                  </ProgressBar>
                )}
              </LabeledList.Item>
            )}
          </LabeledList>

      </Flex.Item>
    </Flex>
  );
};

const OrganScan = (props, context) => {
  const { data } = useBackend(context);
  const {
    advanced,
    bodyparts = [],
  } = data;
  const [organTabIndex, setOrganTabIndex] = useLocalState(context, 'organTabIndex', bodyparts[0].zone);
  const activeZone = bodyparts.find(bodyzone => {
    return bodyzone.zone === organTabIndex;
  });

  return (
    <Flex>
      <Flex.Item>
        <Tabs
          fill
          vertical>
          {bodyparts.map(bodypart => (
            <Tabs.Tab
              key={bodypart.zone}
              selected={organTabIndex === bodypart.zone}
              onClick={() => setOrganTabIndex(bodypart.zone)}>
              {bodypart.zone}
            </Tabs.Tab>
          ))}
        </Tabs>
      </Flex.Item>
      <Flex.Item>
        {!(activeZone.organs.length) && (

            No organs detected.

        )}
        {activeZone.organs.map(organ => (

            <LabeledList>
              <LabeledList.Item
                label={`Name`}>
                {organ.name}
              </LabeledList.Item>
              <LabeledList.Item
                label={`Status`}>
                {organ.status}
              </LabeledList.Item>
              <LabeledList.Item
                label={`Maximum Damage`}>
                {organ.max_damage}
              </LabeledList.Item>
              <LabeledList.Item
                label={`Overall Damage`}
                color={organ.overall_damage !== "Healthy" ? "bad" : "good"}>
                {organ.overall_damage}
              </LabeledList.Item>
              {(advanced ? true : false) && (
                <LabeledList.Item label="Damage">
                  <ProgressBar
                    value={organ.damage/organ.max_damage}
                    color={`bad`}>
                    <AnimatedNumber value={organ.damage} />
                  </ProgressBar>
                </LabeledList.Item>
              )}
              {(advanced ? true : false) && (
                <LabeledList.Item label="Infection Level">
                  <ProgressBar
                    value={organ.germ_level/100}
                    color={`bad`}>
                    <AnimatedNumber value={organ.germ_level} />%
                  </ProgressBar>
                </LabeledList.Item>
              )}
              {(advanced ? false : true) && (
                <LabeledList.Item label="Infection Level">
                  <ProgressBar
                    value={organ.germ_level ? 1 : 0}
                    color={`bad`}>
                    {organ.germ_level ? "Infection" : "No Infection"}
                  </ProgressBar>
                </LabeledList.Item>
              )}
            </LabeledList>
            {(advanced ? true : false) && (
              <Collapsible
                mt={1}
                mx={0.5}
                title={`Efficiencies`}>
                {(organ.efficiencies.length ? true : false) && (

                    <LabeledList>
                      {(organ.efficiencies.map(efficiency => (
                        <LabeledList.Item
                          key={efficiency.slot}
                          label={efficiency.slot}>
                          {efficiency.value}
                        </LabeledList.Item>
                      )))}
                    </LabeledList>

                ) || (

                    No efficiencies detected.

                )}
              </Collapsible>
            )}

        ))}
      </Flex.Item>
    </Flex>
  );
};

const DiseaseScan = (props, context) => {
  const { data } = useBackend(context);
  const {
    diseases = [],
  } = data;

  return (
    <Stack
      fill
      vertical>
      <Stack.Item>
        {diseases.map(disease => (

            <LabeledList>
              <LabeledList.Item label={`Name`}>
                {disease.name}
              </LabeledList.Item>
              <LabeledList.Item label={`Form`}>
                {disease.form}
              </LabeledList.Item>
              <LabeledList.Item label={`Agent`}>
                {disease.agent}
              </LabeledList.Item>
              <LabeledList.Item label={`Spread`}>
                {disease.type}
              </LabeledList.Item>
              <LabeledList.Item label={`Stage`}>
                <ProgressBar
                  value={disease.stage/disease.max_stage}
                  color={`bad`}>
                  <AnimatedNumber value={disease.stage} />
                  / <AnimatedNumber value={disease.max_stage} />
                </ProgressBar>
              </LabeledList.Item>
              <LabeledList.Item label={`Severity`}>
                {disease.severity}
              </LabeledList.Item>
              <LabeledList.Item label={`Hopelessness`}>
                {disease.hopelessness}
              </LabeledList.Item>
              <LabeledList.Item label={`Possible Cure`}>
                {disease.cure}
              </LabeledList.Item>
            </LabeledList>

        ))}
        {(diseases.length ? false : true) && (

            No pathogens detected.

        )}
      </Stack.Item>
    </Stack>
  );
};

const PsychScan = (props, context) => {
  const { data } = useBackend(context);
  const [psychIndex, setPsychIndex] = useLocalState(context, 'psychIndex', 'Brain Traumas');
  const {
    advanced,
    brain_traumas = [],
    major_disabilities = [],
    minor_disabilities = [],
    neutral_disabilities = [],
  } = data;

  return (
    <Stack
      fill
      vertical>
      <Flex>
        <Flex.Item>
          <Tabs
            fill
            vertical>
            <Tabs.Tab
              key={`Brain Traumas`}
              selected={psychIndex === `Brain Traumas`}
              onClick={() => setPsychIndex(`Brain Traumas`)}>
              Brain Traumas
            </Tabs.Tab>
            <Tabs.Tab
              key={`Major Disabilities`}
              selected={psychIndex === `Major Disabilities`}
              onClick={() => setPsychIndex(`Major Disabilities`)}>
              Major Disabilities
            </Tabs.Tab>
            {(advanced ? true : false) && (
              <Tabs.Tab
                key={`Minor Disabilities`}
                selected={psychIndex === `Minor Disabilities`}
                onClick={() => setPsychIndex(`Minor Disabilities`)}>
                Minor Disabilities
              </Tabs.Tab>
            )}
            {(advanced ? true : false) && (
              <Tabs.Tab
                key={`Neutral Disabilities`}
                selected={psychIndex === `Neutral Disabilities`}
                onClick={() => setPsychIndex(`Neutral Disabilities`)}>
                Neutral Disabilities
              </Tabs.Tab>
            )}
          </Tabs>
        </Flex.Item>
        <Flex.Item>
          {(psychIndex === `Brain Traumas`) && (
            <Stack.Item>
              {brain_traumas.map(trauma => (

                  <LabeledList>
                    <LabeledList.Item
                      label={`Name`}>
                      {trauma.name}
                    </LabeledList.Item>
                    <LabeledList.Item
                      label={`Description`}>
                      {trauma.scan_desc}
                    </LabeledList.Item>
                    <LabeledList.Item
                      label={`Severity`}>
                      {trauma.resilience}
                    </LabeledList.Item>
                  </LabeledList>

              ))}
              {(brain_traumas.length ? false : true) && (

                  No brain traumas detected.

              )}
            </Stack.Item>
          )}
          {(psychIndex === `Major Disabilities`) && (
            <Stack.Item>
              {major_disabilities.map(disability => (

                  <LabeledList>
                    <LabeledList.Item
                      label={`Name`}>
                      {disability.name}
                    </LabeledList.Item>
                    <LabeledList.Item
                      label={`Description`}>
                      {disability.scan_desc}
                    </LabeledList.Item>
                  </LabeledList>

              ))}
              {(major_disabilities.length ? false : true) && (

                  No major disabilities detected.

              )}
            </Stack.Item>
          )}
          {(psychIndex === `Minor Disabilities`) && (
            <Stack.Item>
              {advanced ? minor_disabilities.map(disability => (

                  <LabeledList>
                    <LabeledList.Item
                      label={`Name`}>
                      {disability.name}
                    </LabeledList.Item>
                    <LabeledList.Item
                      label={`Description`}>
                      {disability.scan_desc}
                    </LabeledList.Item>
                  </LabeledList>

              )) : null}
              {(advanced && minor_disabilities.length ? false : true) && (

                  No minor disabilities detected.

              )}
            </Stack.Item>
          )}
          {(psychIndex === `Neutral Disabilities`) && (
            <Stack.Item>
              {advanced ? neutral_disabilities.map(disability => (

                  <LabeledList>
                    <LabeledList.Item
                      label={`Name`}>
                      {disability.name}
                    </LabeledList.Item>
                    <LabeledList.Item
                      label={`Description`}>
                      {disability.scan_desc}
                    </LabeledList.Item>
                  </LabeledList>

              )) : null}
              {(advanced && neutral_disabilities.length ? false : true) && (

                  No neutral disabilities detected.

              )}
            </Stack.Item>
          )}
        </Flex.Item>
      </Flex>
    </Stack>
  );
};

const ChemScan = (props, context) => {
  const { data } = useBackend(context);
  const {
    advanced,
    blood_reagents = [],
    stomach_reagents = [],
    intestine_reagents = [],
    bladder_reagents = [],
    addictions = [],
  } = data;

  return (
    <Stack
      fill
      vertical>
      <Collapsible
        title={`Bloodstream Reagents`}>
        {blood_reagents.map(reagent => (

            <LabeledList>
              <LabeledList.Item
                label={`Name`}>
                {reagent.name}
              </LabeledList.Item>
              <LabeledList.Item
                label={`Volume`}>
                <AnimatedNumber value={reagent.volume} />u
              </LabeledList.Item>
              <LabeledList.Item
                color={reagent.overdosing ? "bad" : "good"}
                label={`Overdosing`}>
                {reagent.overdosing ? "Overdosing" : "Not Overdosing"}
              </LabeledList.Item>
            </LabeledList>

        ))}
        {(blood_reagents.length ? false : true) && (

            No reagents detected.

        )}
      </Collapsible>
      <Collapsible
        title={`Stomach Reagents`}>
        {stomach_reagents.map(reagent => (

            <LabeledList>
              <LabeledList.Item
                label={`Name`}>
                {reagent.name}
              </LabeledList.Item>
              <LabeledList.Item
                label={`Volume`}>
                <AnimatedNumber value={reagent.volume} />u
              </LabeledList.Item>
              <LabeledList.Item
                color={reagent.overdosing ? "bad" : "good"}
                label={`Overdosing`}>
                {reagent.overdosing ? "Overdosing" : "Not Overdosing"}
              </LabeledList.Item>
            </LabeledList>

        ))}
        {(stomach_reagents.length ? false : true) && (

            No reagents detected.

        )}
      </Collapsible>
      <Collapsible
        title={`Intestines Reagents`}>
        {intestine_reagents.map(reagent => (

            <LabeledList>
              <LabeledList.Item
                label={`Name`}>
                {reagent.name}
              </LabeledList.Item>
              <LabeledList.Item
                label={`Volume`}>
                <AnimatedNumber value={reagent.volume} />u
              </LabeledList.Item>
              <LabeledList.Item
                color={reagent.overdosing ? "bad" : "good"}
                label={`Overdosing`}>
                {reagent.overdosing ? "Overdosing" : "Not Overdosing"}
              </LabeledList.Item>
            </LabeledList>

        ))}
        {(intestine_reagents.length ? false : true) && (

            No reagents detected.

        )}
      </Collapsible>
      <Collapsible
        title={`Bladder Reagents`}>
        {bladder_reagents.map(reagent => (

            <LabeledList>
              <LabeledList.Item
                label={`Name`}>
                {reagent.name}
              </LabeledList.Item>
              <LabeledList.Item
                label={`Volume`}>
                <AnimatedNumber value={reagent.volume} />u
              </LabeledList.Item>
              <LabeledList.Item
                color={reagent.overdosing ? "bad" : "good"}
                label={`Overdosing`}>
                {reagent.overdosing ? "Overdosing" : "Not Overdosing"}
              </LabeledList.Item>
            </LabeledList>

        ))}
        {(bladder_reagents.length ? false : true) && (

            No reagents detected.

        )}
      </Collapsible>
      <Collapsible
        title={`Addictions`}>
        {addictions.map(addiction => (

            <LabeledList>
              <LabeledList.Item
                label={`Name`}>
                {addiction.name}
              </LabeledList.Item>
              {(advanced ? true : false && (
                <LabeledList.Item
                  label={`Addiction Level`}>
                  <ProgressBar
                    value={addiction.addiction_points/1000}
                    color={`bad`}>
                    <AnimatedNumber
                      value={round(addiction.addiction_points/10, 1)} />%
                  </ProgressBar>
                </LabeledList.Item>
              ))}
            </LabeledList>

        ))}
        {(addictions.length ? false : true) && (

            No addictions detected.

        )}
      </Collapsible>
    </Stack>
  );
};


code:
import { useBackend } from '../backend';
import { Button, Section } from '../components';
import { Window } from '../layouts';

export const Holodeck = (props, context) => {
  const { act, data } = useBackend(context);
  const {
    can_toggle_safety,
    emagged,
    program,
  } = data;
  const default_programs = data.default_programs || [];
  const emag_programs = data.emag_programs || [];
  return (
    <Window
      width={400}
      height={500}>
      <Window.Content scrollable>
        <Section
          title="Default Programs"
          buttons={(
            <Button
              icon={emagged ? "unlock" : "lock"}
              content="Safeties"
              color="bad"
              disabled={!can_toggle_safety}
              selected={!emagged}
              onClick={() => act('safety')} />
          )}>
          {default_programs.map(def_program => (
            <Button
              fluid
              key={def_program.id}
              content={def_program.name.substring(11)}
              textAlign="center"
              selected={def_program.id === program}
              onClick={() => act('load_program', {
                id: def_program.id,
              })} />
          ))}
        </Section>
        {!!emagged && (
          <Section title="Dangerous Programs">
            {emag_programs.map(emag_program => (
              <Button
                fluid
                key={emag_program.id}
                content={emag_program.name.substring(11)}
                color="bad"
                textAlign="center"
                selected={emag_program.id === program}
                onClick={() => act('load_program', {
                  id: emag_program.id,
                })} />
            ))}
          </Section>
        )}
      </Window.Content>
    </Window>
  );
};

repo_name: AnalWerewolf/sundown

license: mit


code:
import { useBackend } from '../backend';
import { Box, Button, Flex, Icon, LabeledList, Modal, NoticeBox, Section } from '../components';
import { Window } from '../layouts';

export const Holopad = (props, context) => {
  const { act, data } = useBackend(context);
  const {
    calling,
  } = data;
  return (
    <Window
      width={440}
      height={245}>
      {!!calling && (
        <Modal
          fontSize="36px"
          fontFamily="monospace">
          <Flex align="center">
            <Flex.Item mr={2} mt={2}>
              <Icon
                name="phone-alt"
                rotation={25} />
            </Flex.Item>
            <Flex.Item mr={2}>
              {'Dialing...'}
            </Flex.Item>
          </Flex>
          <Box
            mt={2}
            textAlign="center"
            fontSize="24px">
            <Button
              lineHeight="40px"
              icon="times"
              content="Hang Up"
              color="bad"
              onClick={() => act('hang_up')} />
          </Box>
        </Modal>
      )}
      <Window.Content scrollable>
        <HolopadContent />
      </Window.Content>
    </Window>
  );
};

const HolopadContent = (props, context) => {
  const { act, data } = useBackend(context);
  const {
    on_network,
    on_cooldown,
    allowed,
    disk,
    disk_record,
    replay_mode,
    loop_mode,
    record_mode,
    holo_calls = [],
  } = data;
  return (
    <>
      <Section
        title="Holopad"
        buttons={(
          <Button
            icon="bell"
            content={on_cooldown
              ? "AI's Presence Requested"
              : "Request AI's Presence"}
            disabled={!on_network || on_cooldown}
            onClick={() => act('AIrequest')} />
        )} >
        <LabeledList>
          <LabeledList.Item label="Communicator">
            <Button
              icon="phone-alt"
              content={allowed ? "Connect To Holopad" : "Call Holopad"}
              disabled={!on_network}
              onClick={() => act('holocall', { headcall: allowed })} />
          </LabeledList.Item>
          {holo_calls.map((call => {
            return (
              <LabeledList.Item
                label={call.connected
                  ? "Current Call"
                  : "Incoming Call"}
                key={call.ref}>
                <Button
                  icon={call.connected ? 'phone-slash' : 'phone-alt'}
                  content={call.connected
                    ? "Disconnect call from " + call.caller
                    : "Answer call from " + call.caller}
                  color={call.connected ? 'bad' : 'good'}
                  disabled={!on_network}
                  onClick={() => act(call.connected
                    ? 'disconnectcall'
                    : 'connectcall', { holopad: call.ref })} />
              </LabeledList.Item>
            );
          }))}
          {holo_calls.filter(call => !call.connected).length > 0 && (
            <LabeledList.Item key="reject">
              <Button
                icon="phone-slash"
                content="Reject incoming call(s)"
                color="bad"
                onClick={() => act('rejectall')} />
            </LabeledList.Item>
          )}
        </LabeledList>
      </Section>
      <Section
        title="Holodisk"
        buttons={
          <Button
            icon="eject"
            content="Eject"
            disabled={!disk || replay_mode || record_mode}
            onClick={() => act('disk_eject')} />
        }>
        {!disk && (
          <NoticeBox>
            No holodisk
          </NoticeBox>
        ) || (
          <LabeledList>
            <LabeledList.Item label="Disk Player">
              <Button
                icon={replay_mode ? 'pause' : 'play'}
                content={replay_mode ? 'Stop' : 'Replay'}
                selected={replay_mode}
                disabled={record_mode || !disk_record}
                onClick={() => act('replay_mode')} />
              <Button
                icon={'sync'}
                content={loop_mode ? 'Looping' : 'Loop'}
                selected={loop_mode}
                disabled={record_mode || !disk_record}
                onClick={() => act('loop_mode')} />
              <Button
                icon="exchange-alt"
                content="Change Offset"
                disabled={!replay_mode}
                onClick={() => act('offset')} />
            </LabeledList.Item>
            <LabeledList.Item label="Recorder">
              <Button
                icon={record_mode ? 'pause' : 'video'}
                content={record_mode ? 'End Recording' : 'Record'}
                selected={record_mode}
                disabled={(disk_record && !record_mode) || replay_mode}
                onClick={() => act('record_mode')} />
              <Button
                icon="trash"
                content="Clear Recording"
                color="bad"
                disabled={!disk_record || replay_mode || record_mode}
                onClick={() => act('record_clear')} />
            </LabeledList.Item>
          </LabeledList>
        )}
      </Section>
    </>
  );
};


code:
import { useBackend } from '../../backend';
import { Box, Button, Icon, Knob, LabeledControls, LabeledList, NumberInput, Section, Tooltip } from '../../components';
import { getGasLabel } from '../../constants';
import { HelpDummy, HoverHelp } from './helpers';

/*
 * This module holds user interactable controls. Some may be good candidates
 * for generalizing and refactoring.
 */

const ComboKnob = (props, context) => {
  const {
    color=false,
    defaultValue,
    icon,
    flipIcon,
    help,
    minValue,
    maxValue,
    parameter,
    step=5,
    value,
    ...rest
  } = props;

  const { act, data } = useBackend(context);

  const iconProps = {};
  if (flipIcon) {
    iconProps.rotation = 180;
  }

  const icon_element = icon && (<Icon
    position="absolute"
    top="16px"
    left="-27px"
    color="label"
    fontSize="200%"
    name={icon}
    {...iconProps}
  />);

  return (
    <Box
      position="relative"
      left="2px">
      {help
        ? (<Tooltip content={help}>{icon_element}</Tooltip>)
        : icon_element}
      <Knob
        color={color}
        size={2}
        value={value}
        minValue={minValue}
        maxValue={maxValue}
        step={step}
        stepPixelSize={1}
        onDrag={(_, v) => act(parameter, { [parameter]: v })}
        {...rest}
      />
      <Button
        fluid
        position="absolute"
        top="-2px"
        right="-20px"
        color="transparent"
        icon="fast-forward"
        onClick={() => act(parameter, { [parameter]: maxValue })}
      />
      <Button
        fluid
        position="absolute"
        top="16px"
        right="-20px"
        color="transparent"
        icon="undo"
        onClick={() => act(parameter, { [parameter]: defaultValue })}
      />
      <Button
        fluid
        position="absolute"
        top="34px"
        right="-20px"
        color="transparent"
        icon="fast-backward"
        onClick={() => act(parameter, { [parameter]: minValue })}
      />
    </Box>
  );
};

export const HypertorusSecondaryControls = (props, context) => {
  const { act, data } = useBackend(context);
  return (

      <LabeledControls justify="space-around" wrap>
        <LabeledControls.Item label="Heating Conductor">
          <ComboKnob
            color={data.heating_conductor > 50 && data.heat_output > 0 && "yellow"}
            value={parseFloat(data.heating_conductor)}
            unit="J/cm"
            minValue={50}
            defaultValue={100}
            maxValue={500}
            parameter="heating_conductor"
            icon="fire"
            help="Adjusts the rate the fusion reaction heats or cools. Higher heating values improve production at the risk of a runaway reaction."
          />
        </LabeledControls.Item>
        <LabeledControls.Item label="Cooling Volume">
          <ComboKnob
            value={parseFloat(data.cooling_volume)}
            unit="L"
            minValue={50}
            defaultValue={100}
            maxValue={2000}
            parameter="cooling_volume"
            step={25}
            icon="snowflake-o"
            help="Adjusts the HFR core's internal cooling space. A smaller space will provide less cooling internally, but will move most of the coolant outside of the HFR core, where it can be rapidly cooled when not needed."
          />
        </LabeledControls.Item>
        <LabeledControls.Item label="Magnetic Constrictor">
          <ComboKnob
            value={parseFloat(data.magnetic_constrictor)}
            unit="m³/T"
            minValue={50}
            defaultValue={100}
            maxValue={1000}
            parameter="magnetic_constrictor"
            icon="magnet"
            flipIcon
            help="Adjusts the density of the fusion reaction. Denser reactions expose more energy, but may destabilize the reaction if too much mass is involved."
          />
        </LabeledControls.Item>
        <LabeledControls.Item label="Current Damper">
          <ComboKnob
            color={data.current_damper && "yellow"}
            value={parseFloat(data.current_damper)}
            unit="W"
            minValue={0}
            defaultValue={0}
            maxValue={1000}
            parameter="current_damper"
            icon="sun-o"
            help="Destabilizes the reaction. A sufficiently destabilized reaction will halt production and become endothermic, cooling the Fusion Mix instead of heating it. Reactions with more iron are harder to destabilize."
          />
        </LabeledControls.Item>
      </LabeledControls>

  );
};

export const HypertorusWasteRemove = (props, context) => {
  const { act, data } = useBackend(context);
  const filterTypes = data.filter_types || [];
  return (

      <LabeledList>
        <LabeledList.Item
          label={
            <>
              <HoverHelp
                content={"Remove waste gases from Fusion,"
                +" and any selected gases from the Moderator."}
              />
              Waste remove:
            </>
          }
        >
          <Button
            icon={data.waste_remove ? 'power-off' : 'times'}
            content={data.waste_remove ? 'On' : 'Off'}
            selected={data.waste_remove}
            onClick={() => act('waste_remove')} />
        </LabeledList.Item>
        <LabeledList.Item
          label={<><HelpDummy />Moderator filtering rate:</>}
        >
          <NumberInput
            animated
            value={parseFloat(data.mod_filtering_rate)}
            unit="mol/s"
            minValue={5}
            maxValue={200}
            onDrag={(e, value) => act('mod_filtering_rate', {
              mod_filtering_rate: value,
            })} />
        </LabeledList.Item>
        <LabeledList.Item
          label={<><HelpDummy />Filter from moderator mix:</>}
        >
          {filterTypes.map(filter => (
            <Button
              key={filter.gas_id}
              icon={filter.enabled ? 'check-square-o' : 'square-o'}
              selected={filter.enabled}
              content={getGasLabel(filter.gas_id, filter.gas_name)}
              onClick={() => act('filter', {
                mode: filter.gas_id,
              })} />
          ))}
        </LabeledList.Item>
      </LabeledList>

  );
};


code:
import { filter, sortBy } from 'common/collections';
import { flow } from 'common/fp';
import { toFixed } from 'common/math';
import { useBackend } from '../../backend';
import { Box, Button, LabeledList, NumberInput, ProgressBar, Section } from '../../components';
import { getGasColor, getGasLabel } from '../../constants';
import { HelpDummy, HoverHelp } from './helpers';

/*
 * Displays contents of gas mixtures, along with help text for gases with
 * special text when present. Some gas bars are always visible, even when
 * absent, to hint at what can be added and their effects.
 */

const moderator_gases_help = {
  plasma: "Produces basic gases. Has a modest heat bonus to help kick start the early fusion process. When added in large quantities, its high heat capacity can help to slow down temperature changes to manageable speeds.",
  bz: "Produces intermediate gases at Fusion Level 3 or higher. Massively increases radiation, and induces hallucinations in bystanders.",
  proto_nitrate: "Produces advanced gases. Massively increases radiation, and accelerates the rate of temperature change. Make sure you have enough cooling.",
  o2: "When added in high quantities, rapidly purges iron content. Does not purge iron content fast enough to keep up with damage at high Fusion Levels.",
  healium: "Directly heals a heavily damaged HFR core at high Fusion Levels, but is rapidly consumed in the process.",
  antinoblium: "Provides huge amounts of energy and radiation. Can cause dangerous electrical storms even from a healthy HFR core when present in more than trace amounts. Wear appropriate electrical protection when handling.",
  freon: "Saps most forms of energy expression. Slows the rate of temperature change.",
};

const moderator_gases_sticky_order = [
  "plasma",
  "bz",
  "proto_nitrate",
];

const ensure_gases = (gas_array, gasids) => {
  const gases_by_id = {};
  gas_array.forEach(gas => { gases_by_id[gas.id] = true; });

  for (let gasid of gasids) {
    if (!gases_by_id[gasid]) {
      gas_array.push({ id: gasid, amount: 0 });
    }
  }
};

const GasList = (props, context) => {
  const { act, data } = useBackend(context);
  const {
    input_max,
    input_min,
    input_rate,
    input_switch,
    gases: raw_gases,
    minimumScale,
    prepend,
    rateHelp,
    stickyGases,
  } = props;

  const gases = flow([
    filter(gas => gas.amount >= 0.01),
    sortBy(gas => -gas.amount),
  ])(raw_gases || []);

  if (stickyGases) {
    ensure_gases(gases, stickyGases);
  }

  return (
    <LabeledList>
      <LabeledList.Item
        label={
          <>
            <HoverHelp content={rateHelp} />
            Injection control:
          </>
        }
      >
        <Button
          disabled={data.start_power === 0
              || data.start_cooling === 0}
          icon={data[input_switch] ? 'power-off' : 'times'}
          content={data[input_switch] ? 'On' : 'Off'}
          selected={data[input_switch]}
          onClick={() => act(input_switch)} />
        <NumberInput
          animated
          value={parseFloat(data[input_rate])}
          unit="mol/s"
          minValue={input_min}
          maxValue={input_max}
          onDrag={(_, v) => act(input_rate, { [input_rate]: v })}
        />
      </LabeledList.Item>
      {gases.map(gas => {
        let labelPrefix;
        if (prepend) {
          labelPrefix = prepend(gas);
        }
        return (
          <LabeledList.Item
            key={gas.id}
            label={
              <>
                {labelPrefix}
                {getGasLabel(gas.id)}:
              </>
            }
          >
            <ProgressBar
              color={getGasColor(gas.id)}
              value={gas.amount}
              minValue={0}
              maxValue={minimumScale}>
              {toFixed(gas.amount, 2) + ' moles'}
            </ProgressBar>
          </LabeledList.Item>);
      })}
    </LabeledList>);
};

export const HypertorusGases = (props, context) => {
  const { data } = useBackend(context);

  const {
    fusion_gases,
    moderator_gases,
  } = data;

  const selected_fuel = (data.selectable_fuel || []).filter(
    d => d.id === data.selected
  )[0];

  return (
    <>

        {selected_fuel
          ? (
            <GasList
              input_rate="fuel_injection_rate"
              input_switch="start_fuel"
              input_max={150}
              input_min={.5}
              gases={fusion_gases}
              minimumScale={500}
              prepend={() => (<HelpDummy />)}
              rateHelp={
                "The rate at which new fuel is added from the fuel input port."
                + " This rate affects the rate of production,"
                + " even when input is not active."
              }
              stickyGases={selected_fuel.requirements}
            />
          )
          : (
            <Box align="center" color="red">
              {"No recipe selected"}
            </Box>
          )}

        <GasList
          input_rate="moderator_injection_rate"
          input_switch="start_moderator"
          input_max={150}
          input_min={.5}
          gases={moderator_gases}
          minimumScale={500}
          rateHelp={"The rate at which new moderator gas is added from the moderator port."}
          stickyGases={moderator_gases_sticky_order}
          prepend={gas =>
            moderator_gases_help[gas.id]
              ? (<HoverHelp content={moderator_gases_help[gas.id]} />)
              : (<HelpDummy />)}
        />

    </>
  );
};


code:
import { toFixed } from 'common/math';
import { useBackend } from '../../backend';
import { Flex, LabeledControls, RoundGauge, Section } from '../../components';
import { formatSiUnit } from '../../format';

/*
 * Parameter display
 *
 * Displays a set of gauges displaying key information about the
 * HFR.
 *
 * Parameters with dangerous thresholds also display warnings at the
 * relevant levels.
 */

export const HypertorusParameters = (props, context) => {
  const { data } = useBackend(context);

  const {
    heat_output,
    heat_output_min,
    heat_output_max,
  } = data;

  const energy_minimum_exponent = 12;
  const energy_minimum_suffix = energy_minimum_exponent / 3;

  let activity = heat_output / (heat_output < 0
    ? heat_output_min
    : heat_output_max);
  if (isNaN(activity) || !isFinite(activity)) {
    activity = 0;
  }

  return (
    <Section title="Reactor Status">
      <Flex className="hypertorus-parameters" justify="space-between" wrap>
        <Flex.Item grow="360" minWidth="120px">
          <LabeledControls justify="space-around" wrap>
            <LabeledControls.Item label="Reactor Integrity">
              <RoundGauge
                size={1.75}
                value={data.integrity}
                minValue={0}
                maxValue={100}
                alertBefore={95}
                format={v => `${Math.round(v)}%`}
                ranges={{
                  good: [90, 100],
                  average: [50, 90],
                  bad: [0, 50],
                }} />
            </LabeledControls.Item>
            <LabeledControls.Item label="Iron Content">
              <RoundGauge
                size={1.75}
                value={data.iron_content}
                minValue={0}
                maxValue={1}
                alertAfter={.25}
                format={v => `${Math.round(v*100)}%`}
                ranges={{
                  good: [0, .1],
                  average: [.1, .36],
                  bad: [.36, 1],
                }} />
            </LabeledControls.Item>
            <LabeledControls.Item label="Area Power">
              <RoundGauge
                size={1.75}
                value={data.apc_energy}
                minValue={0}
                maxValue={100}
                alertBefore={30}
                format={v => `${Math.round(v)}%`}
                ranges={{
                  // Keep these in line with the auto-off thresholds in apc.dm
                  bad: [0, 15],
                  average: [15, 30],
                  good: [30, 100],
                }} />
            </LabeledControls.Item>
          </LabeledControls>
        </Flex.Item>
        <Flex.Item grow="140" minWidth="140px" align="center">
          <LabeledControls justify="space-around">
            <LabeledControls.Item label="Fusion Level">
              <RoundGauge
                size={3}
                minValue={0}
                maxValue={6}
                value={data.power_level}
                alertAfter={4.5}
                ranges={{
                  grey: [0, 1],
                  good: [1, 3.5],
                  average: [3.5, 4.5],
                  bad: [4.5, 6],
                }} />
            </LabeledControls.Item>
          </LabeledControls>
        </Flex.Item>
        <Flex.Item grow="360" minWidth="120px">
          <LabeledControls justify="space-around" wrap>
            <LabeledControls.Item label="Energy">
              <RoundGauge
                size={1.75}
                value={Math.max(0, Math.log10(data.energy_level))}
                minValue={energy_minimum_exponent}
                maxValue={30}
                format={v => formatSiUnit(10**v, energy_minimum_suffix, 'J')}
                ranges={{
                  black: [energy_minimum_exponent, 15],
                  grey: [15, 18], // Anything under 1EJ is pretty mediocre
                  yellow: [18, 24],
                  orange: [24, 30],
                }} />
            </LabeledControls.Item>
            <LabeledControls.Item label="Reaction activity">
              <RoundGauge
                size={1.75}
                value={activity * 100}
                minValue={0}
                maxValue={130} // Proto-nitrate lets us exceed 100%
                format={v => `${data.start_power ? toFixed(v, 1) : 0}%`}
                ranges={{
                  grey: [0, 70],
                  blue: [70, 100],
                  orange: [100, 130],
                }} />
            </LabeledControls.Item>
            <LabeledControls.Item label="Instability">
              <RoundGauge
                size={1.75}
                value={Math.max(data.instability, 0)}
                minValue={0}
                maxValue={10}
                format={v => `${data.start_power ? toFixed(v/8 * 100, 1) : 0}%`}
                ranges={{
                  orange: [0, 8], // exothermic
                  blue: [8, 10], // endothermic
                }} />
            </LabeledControls.Item>
          </LabeledControls>
        </Flex.Item>
      </Flex>
    </Section>
  );
};


code:
import { Box, Button, Icon, Table, Tooltip } from '../../components';
import { getGasColor, getGasLabel } from '../../constants';

/*
 * Recipe selection interface
 *
 * Displays a table of recipes with their outputs and effects, along
 * with buttons to select the active recipe and highlights on the current
 * recipe.
 *
 * Frankly, rather ugly and a good candidate for future improvements.
 */

/**
 * The list of recipe effects to list, in order.
 * Parameters:
 *  - param: The name of the parameter passed in the data object.
 *  - label: The human readable label for this effect.
 *  - scale: The point at which a directional arrow become a
 *           double directional arrow.
 *  - icon:  A string or array of strings describing a pictographic
 *           icon for use with this effect.
 *  - override_base: Optional. Sets the base value for scale calculations
 *                   to something other than 1.
 *  - tooltip: Optional.
 *             If specified, this is passed the value and full data
 *             array and should return the tooltip string.
 *             If omitted, the default of "x{value}" is used.
 *
 */
const recipe_effect_structure = [
  {
    param: "recipe_cooling_multiplier",
    label: "Cooling",
    icon: "snowflake-o",
    scale: 3,
  },
  {
    param: "recipe_heating_multiplier",
    label: "Heating",
    icon: "fire",
    scale: 3,
  },
  {
    param: "energy_loss_multiplier",
    label: "Energy loss",
    icon: "sun-o",
    scale: 3,
  },
  {
    param: "fuel_consumption_multiplier",
    label: "Fuel use",
    icon: ["window-minimize", "arrow-down"],
    scale: 1.5,
  },
  {
    param: "gas_production_multiplier",
    label: "Production",
    icon: ["window-minimize", "arrow-up"],
    scale: 1.5,
  },
  {
    param: "temperature_multiplier",
    label: "Max temperature",
    icon: "thermometer-full",
    override_base: 0.85,
    scale: 1.15,
    tooltip: (v, d) => "Maximum: " + (d.baseMaximumTemperature * v).toExponential() + " K",
  },
];

const effect_to_icon = (effect_value, effect_scale, base) => {
  if (effect_value === base) {
    return "minus";
  }
  if (effect_value > base) {
    if (effect_value > base * effect_scale) {
      return "angle-double-up";
    }
    return "angle-up";
  }
  if (effect_value < base / effect_scale) {
    return "angle-double-down";
  }
  return "angle-down";
};

const recipeChange = {
  onComponentShouldUpdate: (lastProps, nextProps) =>
    lastProps.selectedFuelID !== nextProps.selectedFuelID
    || lastProps.enableRecipeSelection !== nextProps.enableRecipeSelection,
};

const activeChange = {
  onComponentShouldUpdate: (lastProps, nextProps) =>
    lastProps.active !== nextProps.active,
};

const MemoRow = props => {
  const {
    active,
    children,
    key,
    ...rest
  } = props;
  return (
    <Table.Row
      className={`hypertorus-recipes__row${active ? ' hypertorus-recipes__activerow' : ''}`}
      {...rest}
    >
      {children}
    </Table.Row>
  );
};

MemoRow.defaultHooks = activeChange;

const GasCellItem = props => {
  const {
    gasid,
    ...rest
  } = props;
  return (
    <Table.Cell
      key={gasid}
      label={getGasLabel(gasid)} {...rest}>
      <Box color={getGasColor(gasid)}>{getGasLabel(gasid)}</Box>
    </Table.Cell>
  );
};

export const HypertorusRecipes = props => {
  const {
    enableRecipeSelection: enable_recipe_selection,
    onRecipe,
    selectableFuels: selectable_fuels,
    selectedFuelID: selected_fuel_id,
    ...rest
  } = props;
  return (
    <Box overflowX="auto">
      <Table>
        <MemoRow header>
          <Table.Cell />
          <Table.Cell colspan="2">Fuel</Table.Cell>
          <Table.Cell colspan="2">Fusion Byproducts</Table.Cell>
          <Table.Cell colspan="6">Produced gases</Table.Cell>
          <Table.Cell colspan="6">Effects</Table.Cell>
        </MemoRow>
        <MemoRow header>
          <Table.Cell />
          <Table.Cell>Primary</Table.Cell>
          <Table.Cell>Secondary</Table.Cell>
          <Table.Cell colspan="2" />
          <Table.Cell>Tier 1</Table.Cell>
          <Table.Cell>Tier 2</Table.Cell>
          <Table.Cell>Tier 3</Table.Cell>
          <Table.Cell>Tier 4</Table.Cell>
          <Table.Cell>Tier 5</Table.Cell>
          <Table.Cell>Tier 6</Table.Cell>
          {
            // Lay out our pictographic headers for effects.
            recipe_effect_structure.map(item => (
              <Table.Cell key={item.param} color="label">
                <Tooltip content={item.label}>
                  {typeof(item.icon) === "string" ? (
                    <Icon className="hypertorus-recipes__icon" name={item.icon} />
                  ) : (
                    <Icon.Stack className="hypertorus-recipes__icon">
                      {item.icon.map(icon => (
                        <Icon key={icon} name={icon} />
                      ))}
                    </Icon.Stack>
                  )}
                </Tooltip>
              </Table.Cell>
            ))
          }
        </MemoRow>
        {selectable_fuels.filter(d => d.id).map((recipe, index) => {
          const active = recipe.id === selected_fuel_id;
          return (
            <MemoRow key={recipe.id} active={active}>
              <Table.Cell>
                <Button
                  icon={recipe.id === selected_fuel_id ? "times" : "power-off"}
                  disabled={!enable_recipe_selection}
                  key={recipe.id}
                  selected={recipe.id === selected_fuel_id}
                  onClick={onRecipe.bind(null, recipe.id)}
                />
              </Table.Cell>
              <GasCellItem gasid={recipe.requirements[0]} />
              <GasCellItem gasid={recipe.requirements[1]} />
              <GasCellItem gasid={recipe.fusion_byproducts[0]} />
              <GasCellItem gasid={recipe.fusion_byproducts[1]} />
              {recipe.product_gases.map(gasid => (
                <GasCellItem key={gasid} gasid={gasid} />
              ))}
              {
                recipe_effect_structure.map(item => {
                  const value = recipe[item.param];
                  // Note that the minus icon is wider than the arrow icons,
                  // so we set the width to work with both without jumping.
                  return (
                    <Table.Cell key={item.param}>
                      <Tooltip content={(item.tooltip || (v => "x"+v))(value, rest)}>
                        <Icon className="hypertorus-recipes__icon" name={effect_to_icon(value, item.scale, item.override_base || 1)} />
                      </Tooltip>
                    </Table.Cell>
                  );
                })
              }
            </MemoRow>
          );
        })}
      </Table>
    </Box>
  );
};

HypertorusRecipes.defaultHooks = recipeChange;


code:
import { useBackend } from '../../backend';
import { Box, Flex, Icon, Section, Stack, Tooltip } from '../../components';
import { to_exponential_if_big } from './helpers';

/*
 * Shows a set of temperatures on a unified temperature scale.
 *
 * Axis labels draw attention to points of interest.
 *
 * This is a good candidate for refactoring into something reusable, or
 * maybe extending ProgressBar.
 */

/**
 * Note: This must be kept in sync with Hypertorus.scss
 */
const height = 200;

const VerticalBar = props => {
  const {
    color,
    value,
    progressHeight,
  } = props;
  let y = height - progressHeight;
  return (

      {!!value && (<Box backgroundColor={color} top={`${y}px`} />)}

);
};

const BarLabel = (props) => {
  const {
    label,
    delta,
    value,
  } = props;

  return (
    <>
      <Box align="center">{label}</Box>
      {value > 0
        ? (
          <>
            <Box align="center">{to_exponential_if_big(value) + " K"}</Box>
            <Box align="center">{(delta === 0
              ? '-'
              : `${delta < 0 ? '' : '+'}${to_exponential_if_big(delta)} K/s`
            )}
            </Box>
          </>)
        : (
          <>
            <Box align="center" color="red">Empty</Box>
            <Box class="hypertorus__unselectable"
              {...(Byond.IS_LTE_IE8 ? { style: { unselectable: true } } : {})}
            >

            </Box>
          </>
        )}
    </>);
};

export const HypertorusTemperatures = (props, context) => {
  const { data } = useBackend(context);

  const {
    power_level,
    base_max_temperature,
    internal_fusion_temperature,
    moderator_internal_temperature,
    internal_output_temperature,
    internal_coolant_temperature,
    temperature_period,
  } = data;

  const internal_fusion_temperature_delta = (internal_fusion_temperature
    - data.internal_fusion_temperature_archived) / temperature_period;
  const internal_output_temperature_delta = (internal_output_temperature
    - data.internal_output_temperature_archived) / temperature_period;
  const internal_coolant_temperature_delta = (internal_coolant_temperature
    - data.internal_coolant_temperature_archived) / temperature_period;
  const moderator_internal_temperature_delta = (moderator_internal_temperature
    - data.moderator_internal_temperature_archived) / temperature_period;

  const selected_fuel = (data.selectable_fuel || []).filter(
    d => d.id === data.selected
  )[0];

  let prev_power_level_temperature = 10 ** (1+power_level);
  let next_power_level_temperature = 10 ** (2+power_level);

  if (power_level === 0) {
    prev_power_level_temperature = 0;
    next_power_level_temperature = 500;
  } else if (power_level === 1) {
    prev_power_level_temperature = 500;
  } else if (power_level === 6) {
    next_power_level_temperature = base_max_temperature
      * (selected_fuel ? selected_fuel.temperature_multiplier : 1);
  }

  const temperatures = [
    prev_power_level_temperature,
    next_power_level_temperature,
    ...[
      internal_fusion_temperature,
      moderator_internal_temperature,
      internal_output_temperature,
      internal_coolant_temperature,
    ].filter(d => d),
  ].map(d => parseFloat(d));

  const maxTemperature = Math.max(...temperatures);
  const minTemperature = Math.max(
    2.73,
    Math.min(20, ...temperatures.filter(d => d>0))
  );

  if (power_level === 6) {
    next_power_level_temperature = 0;
  }

  const value_to_y = (value, baseTemp = minTemperature, fromBottom=false) => {
    const ratio = (Math.log10(value) - Math.log10(baseTemp))
      / (Math.log10(maxTemperature) - Math.log10(minTemperature));
    return height * (fromBottom ? (1 - ratio) : ratio);
  };

  const TemperatureLabel = props => {
    const {
      icon,
      force,
      tooltip,
      value,
    } = props;
    const y = value_to_y(value);
    const label = (
      <Box className="hypertorus-temperatures__y-axis-label">
        {icon && (
          <Icon
            className="hypertorus-temperatures__y-axis-label-icon"
            name={icon}
          />)}
        {to_exponential_if_big(value) + " K"}
      </Box>
    );
    return (!!value || force) && (
      <Box class="hypertorus-temperatures__y-axis-tick-anchor" top={`${height - y}px`}>
        <Box className="hypertorus-temperatures__y-axis-tick" />
        {tooltip
          ? (<Tooltip content={tooltip}>{label}</Tooltip>)
          : label}
      </Box>
    );
  };

  const TemperatureBar = (props) => {
    const {
      label,
      delta,
      value,
      children,
      ...rest
    } = props;
    const y = value_to_y(value);
    return (
      <Flex.Item mx={1}>
        <Stack vertical align="center">
          <Stack.Item>
            <VerticalBar
              progressHeight={y}
              value={value}
              {...rest}
            >
              {children}
            </VerticalBar>
          </Stack.Item>
          <Stack.Item color="label">
            <BarLabel delta={delta} label={label} value={value} />
          </Stack.Item>
        </Stack>
      </Flex.Item>
    );
  };

  // Make sure that our labels are legible before displaying them.
  // If two axis labels are too close to one another, don't show them.
  const clutter_threshold = 20;
  const label_legible = (l, r) =>
    Math.abs(value_to_y(l) - value_to_y(r)) > clutter_threshold;

  const show_min = label_legible(prev_power_level_temperature, minTemperature)
    || power_level === 0;
  const show_max = label_legible(next_power_level_temperature, maxTemperature);

  return (

      <Box className="hypertorus-temperatures__container">
        <Box className="hypertorus-temperatures__y-axis-marks">
          {show_min && (
            <TemperatureLabel key="min_temp"
              value={minTemperature}
              force
            />
          )}
          <TemperatureLabel key="prev_fusion_temp"
            icon="chevron-down"
            tooltip="Previous Fusion Level"
            value={prev_power_level_temperature}
          />
          <TemperatureLabel key="next_fusion_temp"
            icon="chevron-up"
            tooltip="Next Fusion Level"
            value={next_power_level_temperature}
          />
          {show_max && (
            <TemperatureLabel key="max_temp"
              value={maxTemperature}
            />
          )}
        </Box>
        <Box className="hypertorus-temperatures__y-axis">
          <Box className="hypertorus-temperatures__x-axis" />
        </Box>
        <Flex overflowY="hidden" className="hypertorus-temperatures__chart" justify="space-around">
          <TemperatureBar
            label="Fusion"
            value={internal_fusion_temperature}
            delta={internal_fusion_temperature_delta}
            color="#f2711c" />
          <TemperatureBar
            label="Moderator"
            value={moderator_internal_temperature}
            delta={moderator_internal_temperature_delta}
            color="#e03997" />
          <TemperatureBar
            label="Coolant"
            value={internal_coolant_temperature}
            delta={internal_coolant_temperature_delta}
            color="aliceblue" />
          <TemperatureBar
            label="Output"
            value={internal_output_temperature}
            delta={internal_output_temperature_delta}
            color="#20b142" />
        </Flex>
      </Box>

  );
};


code:
import { Icon, Tooltip } from '../../components';

// Exponential rendering specifically for HFR values.
// Note that we don't want to use unicode exponents as anything over ^3
// is more or less unreadable.
export const to_exponential_if_big = (value) => {
  if (Math.abs(value) > 5000) {
    return value.toExponential(1);
  }
  return Math.round(value);
};

// Simple question mark icon with a hover tooltip
export const HoverHelp = props => (
  <Tooltip content={props.content}>
    <Icon name="question-circle" width="12px" mr="6px" />
  </Tooltip>
);

// When no hover help is available, but we want a placeholder for spacing
export const HelpDummy = props => (
  <Icon name="" width="12px" mr="6px" />
);


code:
import { useBackend } from 'tgui/backend';
import { Button, Collapsible, Flex, Section, Stack } from 'tgui/components';
import { Window } from 'tgui/layouts';
import { HypertorusSecondaryControls, HypertorusWasteRemove } from './Controls';
import { HypertorusGases } from './Gases';
import { HypertorusParameters } from './Parameters';
import { HypertorusRecipes } from './Recipes';
import { HypertorusTemperatures } from './Temperatures';

const HypertorusMainControls = (props, context) => {
  const { act, data } = useBackend(context);

  return (
    <Section title="Startup">
      <Stack>
        <Stack.Item color="label">
          {'Start power: '}
          <Button
            disabled={data.power_level > 0}
            icon={data.start_power ? 'power-off' : 'times'}
            content={data.start_power ? 'On' : 'Off'}
            selected={data.start_power}
            onClick={() => act('start_power')} />
        </Stack.Item>
        <Stack.Item color="label">
          {'Start cooling: '}
          <Button
            disabled={data.start_fuel === 1
                || data.start_moderator === 1
                || data.start_power === 0
                || (data.start_cooling && data.power_level > 0)}
            icon={data.start_cooling ? 'power-off' : 'times'}
            content={data.start_cooling ? 'On' : 'Off'}
            selected={data.start_cooling}
            onClick={() => act('start_cooling')} />
        </Stack.Item>
      </Stack>
      <Collapsible title="Recipe selection">
        <HypertorusRecipes
          baseMaximumTemperature={data.base_max_temperature}
          enableRecipeSelection={data.power_level === 0}
          onRecipe={id => act('fuel', { mode: id })}
          selectableFuels={data.selectable_fuel}
          selectedFuelID={data.selected}
        />
      </Collapsible>
    </Section>
  );
};

const HypertorusLayout = () => {
  return (
    <Flex className="hypertorus-layout" wrap>
      <Flex.Item grow width="100%">
        <HypertorusMainControls />
      </Flex.Item>
      <Flex.Item grow="20" width="350px" minWidth="280px">
        <HypertorusGases />
      </Flex.Item>
      <Flex.Item grow width="420px" overflowX="auto">
        <HypertorusTemperatures />
      </Flex.Item>
      <Flex.Item grow="4" width="580px">
        <Flex className="hypertorus-layout" wrap>
          <Flex.Item grow width="860px">
            <HypertorusParameters />
          </Flex.Item>
          <Flex.Item grow width="580px">
            <HypertorusSecondaryControls />
          </Flex.Item>
        </Flex>
      </Flex.Item>
      <Flex.Item grow width="100%">
        <HypertorusWasteRemove />
      </Flex.Item>
    </Flex>
  );
};

export const Hypertorus = (props, context) => {
  // The HFR has a ridiculous amount of knobs and information.
  // Ideally we'd display a large window for it all...
  const idealWidth = 850, idealHeight = 980;

  // ...but we should check for small screens, to play nicely with eg laptops.
  const winWidth  = window.screen.availWidth;
  const winHeight = window.screen.availHeight;

  // Make sure we don't start larger than 50%/80% of screen width/height.
  const width = Math.min(idealWidth, winWidth * 0.5);
  const height = Math.min(idealHeight, winHeight * 0.8);

  return (
    <Window
      title="Hypertorus Fusion Reactor control panel"
      width={width}
      height={height}>
      <Window.Content scrollable>
        <HypertorusLayout />
      </Window.Content>
    </Window>
  );
};


code:
import { useBackend } from '../backend';
import { Button, Icon, Input, LabeledList, Section } from '../components';
import { Window } from '../layouts';

export const HypnoChair = (props, context) => {
  const { act, data } = useBackend(context);
  return (
    <Window
      width={375}
      height={480}>
      <Window.Content>
        <Section
          title="Information"
          backgroundColor="#450F44">
          The Enhanced Interrogation Chamber is designed to induce a
          deep-rooted trance trigger into the subject. Once the procedure
          is complete, by using the implanted trigger phrase, the
          authorities are able to ensure immediate and complete obedience
          and truthfulness.
        </Section>
        <Section
          title="Occupant Information"
          textAlign="center">
          <LabeledList>
            <LabeledList.Item label="Name">
              {data.occupant.name ? data.occupant.name : 'No Occupant'}
            </LabeledList.Item>
            {!!data.occupied && (
              <LabeledList.Item
                label="Status"
                color={data.occupant.stat === 0
                  ? 'good'
                  : data.occupant.stat === 1
                    ? 'average'
                    : 'bad'}>
                {data.occupant.stat === 0
                  ? 'Conscious'
                  : data.occupant.stat === 1
                    ? 'Unconcious'
                    : 'Dead'}
              </LabeledList.Item>
            )}
          </LabeledList>
        </Section>
        <Section
          title="Operations"
          textAlign="center">
          <LabeledList>
            <LabeledList.Item label="Door">
              <Button
                icon={data.open ? 'unlock' : 'lock'}
                color={data.open ? 'default' : 'red'}
                content={data.open ? 'Open' : 'Closed'}
                onClick={() => act('door')} />
            </LabeledList.Item>
            <LabeledList.Item label="Trigger Phrase">
              <Input
                value={data.trigger}
                onChange={(e, value) => act('set_phrase', {
                  phrase: value,
                })} />
            </LabeledList.Item>
            <LabeledList.Item label="Interrogate Occupant">
              <Button
                icon="code-branch"
                content={data.interrogating
                  ? "Interrupt Interrogation"
                  : 'Begin Enhanced Interrogation'}
                onClick={() => act('interrogate')} />
              {data.interrogating === 1 && (
                <Icon
                  name="cog"
                  color="orange"
                  spin />
              )}
            </LabeledList.Item>
          </LabeledList>
        </Section>
      </Window.Content>
    </Window>
  );
};


code:
import { useBackend } from '../backend';
import { Button, Icon, LabeledList, Section } from '../components';
import { Window } from '../layouts';

export const ImplantChair = (props, context) => {
  const { act, data } = useBackend(context);
  return (
    <Window
      width={375}
      height={280}>
      <Window.Content>
        <Section
          title="Occupant Information"
          textAlign="center">
          <LabeledList>
            <LabeledList.Item label="Name">
              {data.occupant.name || 'No Occupant'}
            </LabeledList.Item>
            {!!data.occupied && (
              <LabeledList.Item
                label="Status"
                color={data.occupant.stat === 0
                  ? 'good'
                  : data.occupant.stat === 1
                    ? 'average'
                    : 'bad'}>
                {data.occupant.stat === 0
                  ? 'Conscious'
                  : data.occupant.stat === 1
                    ? 'Unconcious'
                    : 'Dead'}
              </LabeledList.Item>
            )}
          </LabeledList>
        </Section>
        <Section
          title="Operations"
          textAlign="center">
          <LabeledList>
            <LabeledList.Item label="Door">
              <Button
                icon={data.open ? 'unlock' : 'lock'}
                color={data.open ? 'default' : 'red'}
                content={data.open ? 'Open' : 'Closed'}
                onClick={() => act('door')} />
            </LabeledList.Item>
            <LabeledList.Item label="Implant Occupant">
              <Button
                icon="code-branch"
                content={data.ready
                  ? (data.special_name || 'Implant')
                  : 'Recharging'}
                onClick={() => act('implant')} />
              {data.ready === 0 && (
                <Icon
                  name="cog"
                  color="orange"
                  spin />
              )}
            </LabeledList.Item>
            <LabeledList.Item label="Implants Remaining">
              {data.ready_implants}
              {data.replenishing === 1 && (
                <Icon
                  name="sync"
                  color="red"
                  spin />
              )}
            </LabeledList.Item>
          </LabeledList>
        </Section>
      </Window.Content>
    </Window>
  );
};


code:
import { useBackend } from '../backend';
import { Button, Section, LabeledList } from '../components';
import { Window } from '../layouts';

export const InfraredEmitter = (props, context) => {
  const { act, data } = useBackend(context);
  const {
    on,
    visible,
  } = data;
  return (
    <Window
      width={225}
      height={110}>
      <Window.Content>
        <Section>
          <LabeledList>
            <LabeledList.Item label="Status">
              <Button
                icon={on ? 'power-off' : 'times'}
                content={on ? 'On' : 'Off'}
                selected={on}
                onClick={() => act('power')} />
            </LabeledList.Item>
            <LabeledList.Item label="Visibility">
              <Button
                icon={visible ? 'eye' : 'eye-slash'}
                content={visible ? 'Visible' : 'Invisible'}
                selected={visible}
                onClick={() => act('visibility')} />
            </LabeledList.Item>
          </LabeledList>
        </Section>
      </Window.Content>
    </Window>
  );
};


code:
import { Stack, Button } from '../../components';

export const BasicInput = (props, context) => {
  const { children, name, setValue, defaultValue, value } = props;
  return (
    (value !== null && (
      <Stack onMouseDown={(e) => e.stopPropagation()}>
        <Stack.Item>
          <Button
            color="transparent"
            compact
            icon="times"
            onClick={() => setValue(null, { set_null: true })}
          />
        </Stack.Item>
        <Stack.Item>{children}</Stack.Item>
      </Stack>
    )) || (
      <Button
        content={name}
        color="transparent"
        compact
        onClick={() => setValue(defaultValue)}
      />
    )
  );
};


code:
import { Button, Stack, Box } from '../../components';

export const CircuitInfo = (props, context) => {
  const {
    name,
    desc,
    notices,
    ...rest
  } = props;
  return (
    <Box {...rest}>
      <Stack fill vertical justify="space-around">
        <Stack.Item maxWidth="200px">
          {desc}
        </Stack.Item>
        <Stack.Item>
          <Stack vertical>
            {notices.map((val, index) => (
              <Stack.Item key={index}>
                <Button
                  content={val.content}
                  color={val.color}
                  icon={val.icon}
                  fluid
                />
              </Stack.Item>
            ))}
          </Stack>
        </Stack.Item>
      </Stack>
    </Box>
  );
};


code:
import { CSS_COLORS } from '../../constants';
import { SVG_CURVE_INTENSITY } from './constants';
import { classes } from '../../../common/react';

export const Connections = (props, context) => {
  const { connections } = props;

  const isColorClass = (str) => {
    if (typeof str === 'string') {
      return CSS_COLORS.includes(str);
    }
  };

  return (
    <svg
      width="100%"
      height="100%"
      style={{
        'position': 'absolute',
        'pointer-events': 'none',
        'z-index': -1,
      }}>
      {connections.map((val, index) => {
        const from = val.from;
        const to = val.to;
        if (!to || !from) {
          return;
        }
        // Starting point
        let path = `M ${from.x} ${from.y}`;
        // DEFAULT STYLE
        path += `C ${from.x + SVG_CURVE_INTENSITY}, ${from.y},`;
        path += `${to.x - SVG_CURVE_INTENSITY}, ${to.y},`;
        path += `${to.x}, ${to.y}`;

        // SUBWAY STYLE
        // const yDiff = Math.abs(from.y - (to.y - 16));
        // path += `L ${to.x - yDiff} ${from.y}`;
        // path += `L ${to.x - 16} ${to.y}`;
        // path += `L ${to.x} ${to.y}`;

        val.color = val.color || 'blue';
        return (
          <path
            className={classes([
              isColorClass(val.color) && `color-stroke-${val.color}`,
            ])}
            key={index}
            d={path}
            fill="transparent"
            stroke-width="2px"
          />
        );
      })}
    </svg>
  );
};


code:
import { useBackend } from '../../backend';
import { Box, Button, Flex } from '../../components';
import { FUNDAMENTAL_DATA_TYPES, DATATYPE_DISPLAY_HANDLERS } from './FundamentalTypes';

export const DisplayName = (props, context) => {
  const { act } = useBackend(context);
  const { port, isOutput, componentId, portIndex, ...rest } = props;

  const InputComponent = FUNDAMENTAL_DATA_TYPES[port.type || 'unknown'];
  const TypeDisplayHandler = DATATYPE_DISPLAY_HANDLERS[port.type || 'unknown'];

  const hasInput = !isOutput
    && !port.connected_to?.length
    && InputComponent;

  const displayType = TypeDisplayHandler? TypeDisplayHandler(port) : port.type;

  return (
    <Box {...rest}>
      <Flex direction="column">
        <Flex.Item textAlign={isOutput? "right" : "left"}>
          {(hasInput && (
            <InputComponent
              setValue={(val, extraParams) =>
                act('set_component_input', {
                  component_id: componentId,
                  port_id: portIndex,
                  input: val,
                  ...extraParams,
                })}
              color={port.color}
              name={port.name}
              value={port.current_data}
              extraData={port.datatype_data}
            />
          ))
            || (isOutput && (
              <Button
                compact
                color="transparent"
                onClick={() =>
                  act('get_component_value', {
                    component_id: componentId,
                    port_id: portIndex,
                  })}>
                <Box color="white">{port.name}</Box>
              </Button>
            ))
            || port.name}
        </Flex.Item>
        <Flex.Item>
          <Box
            fontSize={0.75}
            opacity={0.25}
            textAlign={isOutput ? 'right' : 'left'}>
            {displayType || 'unknown'}
          </Box>
        </Flex.Item>
      </Flex>
    </Box>
  );
};


code:
import { BasicInput } from './BasicInput';
import { NumberInput, Button, Stack, Input, Dropdown } from '../../components';
import { OPTION_DROPDOWN_LARGE_CHAR_AMOUNT } from './constants';

export const FUNDAMENTAL_DATA_TYPES = {
  'string': (props, context) => {
    const { name, value, setValue, color } = props;
    return (
      <BasicInput name={name} setValue={setValue} value={value} defaultValue="">
        <Input
          placeholder={name}
          value={value}
          onChange={(e, val) => setValue(val)}
          width="96px"
        />
      </BasicInput>
    );
  },
  'number': (props, context) => {
    const { name, value, setValue, color } = props;
    return (
      <BasicInput
        name={name}
        setValue={setValue}
        value={value}
        defaultValue={0}>
        <NumberInput
          value={value}
          color={color}
          onChange={(e, val) => setValue(val)}
          unit={name}
        />
      </BasicInput>
    );
  },
  'entity': (props, context) => {
    const { name, setValue } = props;
    return (
      <Button
        content={name}
        color="transparent"
        icon="upload"
        compact
        onClick={() => setValue(null, { marked_atom: true })}
      />
    );
  },
  'datum': (props, context) => {
    const { name, setValue } = props;
    return (
      <Button
        content={name}
        color="transparent"
        icon="upload"
        compact
        onClick={() => setValue(null, { marked_atom: true })}
      />
    );
  },
  'signal': (props, context) => {
    const { name, setValue } = props;
    return (
      <Button
        content={name}
        color="transparent"
        compact
        onClick={() => setValue()}
      />
    );
  },
  'option': (props, context) => {
    const { value, setValue, extraData } = props;
    let large = false;
    const data = Array.isArray(extraData)
      ? extraData
      : Object.keys(extraData);

    data.forEach(element => {
      if (element.length > OPTION_DROPDOWN_LARGE_CHAR_AMOUNT) {
        large = true;
      }
    });

    return (
      <Dropdown
        className="Datatype__Option"
        color={"transparent"}
        options={data}
        onSelected={setValue}
        displayText={value}
        openWidth={large ? "200px" : undefined}
        noscroll
      />
    );
  },
  'any': (props, context) => {
    const { name, value, setValue, color } = props;
    return (
      <BasicInput
        name={name}
        setValue={setValue}
        value={value}
        defaultValue={''}>
        <Stack>
          <Stack.Item>
            <Button
              color={color}
              icon="upload"
              onClick={() => setValue(null, { marked_atom: true })}
            />
          </Stack.Item>
          <Stack.Item>
            <Input
              placeholder={name}
              value={value}
              onChange={(e, val) => setValue(val)}
              width="64px"
            />
          </Stack.Item>
        </Stack>
      </BasicInput>
    );
  },
};

export const DATATYPE_DISPLAY_HANDLERS = {
  'option': (port) => {
    return port.name.toLowerCase();
  },
};


code:
import { useBackend } from '../../backend';
import {
  Box,
  Stack, Button,
} from '../../components';
import { Component } from 'inferno';
import { shallowDiffers } from '../../../common/react';
import { ABSOLUTE_Y_OFFSET } from './constants';
import { Port } from "./Port";

export class ObjectComponent extends Component {
  constructor() {
    super();
    this.state = {
      isDragging: false,
      dragPos: null,
      startPos: null,
      lastMousePos: null,
    };

    this.handleStartDrag = this.handleStartDrag.bind(this);
    this.handleStopDrag = this.handleStopDrag.bind(this);
    this.handleDrag = this.handleDrag.bind(this);
  }

  handleStartDrag(e) {
    const { x, y } = this.props;
    e.stopPropagation();
    this.setState({
      lastMousePos: null,
      isDragging: true,
      dragPos: { x: x, y: y },
      startPos: { x: x, y: y },
    });
    window.addEventListener('mousemove', this.handleDrag);
    window.addEventListener('mouseup', this.handleStopDrag);
  }

  handleStopDrag(e) {
    const { act } = useBackend(this.context);
    const { dragPos } = this.state;
    const { index } = this.props;
    if (dragPos) {
      act('set_component_coordinates', {
        component_id: index,
        rel_x: dragPos.x,
        rel_y: dragPos.y,
      });
    }

    window.removeEventListener('mousemove', this.handleDrag);
    window.removeEventListener('mouseup', this.handleStopDrag);
    this.setState({ isDragging: false });
  }

  handleDrag(e) {
    const { dragPos, isDragging, lastMousePos } = this.state;
    if (dragPos && isDragging) {
      e.preventDefault();
      const { screenZoomX, screenZoomY, screenX, screenY } = e;
      let xPos = screenZoomX || screenX;
      let yPos = screenZoomY || screenY;
      if (lastMousePos) {
        this.setState({
          dragPos: {
            x: dragPos.x - (lastMousePos.x - xPos),
            y: dragPos.y - (lastMousePos.y - yPos),
          },
        });
      }
      this.setState({
        lastMousePos: { x: xPos, y: yPos },
      });
    }
  }

  shouldComponentUpdate(nextProps, nextState) {
    const { input_ports, output_ports } = this.props;

    return (
      shallowDiffers(this.props, nextProps)
      || shallowDiffers(this.state, nextState)
      || shallowDiffers(input_ports, nextProps.input_ports)
      || shallowDiffers(output_ports, nextProps.output_ports)
    );
  }

  render() {
    const {
      input_ports,
      output_ports,
      name,
      x,
      y,
      index,
      color = 'blue',
      removable,
      ui_buttons,
      locations,
      onPortUpdated,
      onPortLoaded,
      onPortMouseDown,
      onPortRightClick,
      onPortMouseUp,
      ...rest
    } = this.props;
    const { act } = useBackend(this.context);
    const { startPos, dragPos } = this.state;

    let [x_pos, y_pos] = [x, y];
    if (dragPos && startPos && startPos.x === x_pos && startPos.y === y_pos) {
      x_pos = dragPos.x;
      y_pos = dragPos.y;
    }

    // Assigned onto the ports
    const PortOptions = {
      onPortLoaded: onPortLoaded,
      onPortUpdated: onPortUpdated,
      onPortMouseDown: onPortMouseDown,
      onPortRightClick: onPortRightClick,
      onPortMouseUp: onPortMouseUp,
    };

    return (
      <Box
        {...rest}
        position="absolute"
        left={`${x_pos}px`}
        top={`${y_pos}px`}
        onMouseDown={this.handleStartDrag}
        onMouseUp={this.handleStopDrag}
        onComponentWillUnmount={this.handleDrag}>
        <Box
          backgroundColor={color}
          py={1}
          px={1}
          className="ObjectComponent__Titlebar">
          <Stack>
            <Stack.Item grow={1} unselectable="on">
              {name}
            </Stack.Item>
            {!!ui_buttons && Object.keys(ui_buttons).map(icon => (
              <Stack.Item key={icon}>
                <Button
                  icon={icon}
                  color="transparent"
                  compact
                  onClick={() => act('perform_action', {
                    component_id: index,
                    action_name: ui_buttons[icon],
                  })}
                />
              </Stack.Item>
            ))}
            <Stack.Item>
              <Button
                color="transparent"
                icon="info"
                compact
                onClick={(e) => act('set_examined_component', {
                  component_id: index,
                  x: e.pageX,
                  y: e.pageY + ABSOLUTE_Y_OFFSET,
                })} />
            </Stack.Item>
            {!!removable && (
              <Stack.Item>
                <Button
                  color="transparent"
                  icon="times"
                  compact
                  onClick={() => act('detach_component', { component_id: index })} />
              </Stack.Item>
            )}
          </Stack>
        </Box>
        <Box
          className="ObjectComponent__Content"
          unselectable="on"
          py={1}
          px={1}>
          <Stack>
            <Stack.Item>
              <Stack vertical fill>
                {input_ports.map((port, portIndex) => (
                  <Stack.Item key={portIndex}>
                    <Port
                      port={port}
                      portIndex={portIndex + 1}
                      componentId={index}
                      {...PortOptions}
                    />
                  </Stack.Item>
                ))}
              </Stack>
            </Stack.Item>
            <Stack.Item ml={5}>
              <Stack vertical>
                {output_ports.map((port, portIndex) => (
                  <Stack.Item key={portIndex}>
                    <Port
                      port={port}
                      portIndex={portIndex + 1}
                      componentId={index}
                      {...PortOptions}
                      isOutput />
                  </Stack.Item>
                ))}
              </Stack>
            </Stack.Item>
          </Stack>
        </Box>
      </Box>
    );
  }
}


code:
import {
  Stack,
  Box,
} from '../../components';
import { Component, createRef } from 'inferno';
import { DisplayName } from "./DisplayName";
import { classes } from 'common/react';

export class Port extends Component {
  constructor() {
    super();
    this.iconRef = createRef();
    this.componentDidUpdate = this.componentDidUpdate.bind(this);
    this.componentDidMount = this.componentDidMount.bind(this);
    this.handlePortMouseDown = this.handlePortMouseDown.bind(this);
    this.handlePortRightClick = this.handlePortRightClick.bind(this);
    this.handlePortMouseUp = this.handlePortMouseUp.bind(this);
  }

  handlePortMouseDown(e) {
    const {
      port,
      portIndex,
      componentId,
      isOutput,
      onPortMouseDown,
    } = this.props;
    onPortMouseDown(portIndex, componentId, port, isOutput, e);
  }

  handlePortMouseUp(e) {
    const {
      port,
      portIndex,
      componentId,
      isOutput,
      onPortMouseUp,
    } = this.props;
    onPortMouseUp(portIndex, componentId, port, isOutput, e);
  }

  handlePortRightClick(e) {
    const {
      port,
      portIndex,
      componentId,
      isOutput,
      onPortRightClick,
    } = this.props;
    onPortRightClick(portIndex, componentId, port, isOutput, e);
  }

  componentDidUpdate() {
    const { port, onPortUpdated } = this.props;
    if (onPortUpdated) {
      onPortUpdated(port, this.iconRef.current);
    }
  }

  componentDidMount() {
    const { port, onPortLoaded } = this.props;
    if (onPortLoaded) {
      onPortLoaded(port, this.iconRef.current);
    }
  }

  renderDisplayName() {
    const {
      port,
      portIndex,
      componentId,
      isOutput,
    } = this.props;

    return (
      <Stack.Item>
        <DisplayName
          port={port}
          isOutput={isOutput}
          componentId={componentId}
          portIndex={portIndex} />
      </Stack.Item>
    );
  }

  render() {
    const {
      port,
      isOutput,
      ...rest
    } = this.props;

    let composite_types = [];
    if (port.datatype_data?.composite_types) {
      composite_types = port.datatype_data.composite_types;
    }

    return (
      <Stack
        {...rest}
        justify={isOutput ? 'flex-end' : 'flex-start'}
      >
        {!!isOutput && this.renderDisplayName()}
        <Stack.Item>
          <Box
            className={classes([
              "ObjectComponent__Port",
            ])}
            onMouseDown={this.handlePortMouseDown}
            onContextMenu={this.handlePortRightClick}
            onMouseUp={this.handlePortMouseUp}
            textAlign="center"
          >
            <svg
              style={{
                width: "100%",
                height: "100%",
                position: "absolute",
              }}
              viewBox="0, 0, 100, 100"
            >
              {composite_types.map((compositeColor, index) => {
                const radians = (2*Math.PI)/composite_types.length;
                const arcLength = radians*50;
                return (
                  <circle
                    key={index}
                    stroke={compositeColor}
                    strokeDasharray={`${arcLength}, ${100*Math.PI}`}
                    strokeDashoffset={
                      -index*(100*(Math.PI/composite_types.length))
                    }
                    className={`color-stroke-${compositeColor}`}
                    strokeWidth="50px"
                    cx="50"
                    cy="50"
                    r="50"
                    fillOpacity="0"
                    transform="rotate(90, 50, 50)"
                  />
                );
              })}
              <circle ref={this.iconRef} cx="50" cy="50" r="50" className={`color-fill-${port.color}`} />
            </svg>
            <span ref={this.iconRef} className="ObjectComponent__PortPos" />
          </Box>
        </Stack.Item>
        {!isOutput && this.renderDisplayName()}
      </Stack>
    );
  }
}