happy-combo / index.html
web3district's picture
make the petals multi coloured by layers - Initial Deployment
436dafb verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>RFH Intelligent Visualizer</title>
<style>
:root { --happiness: 0; }
body {
font-family: 'Segoe UI', sans-serif;
display: flex; justify-content: center; align-items: center;
min-height: 100vh; margin: 0; padding: 20px;
transition: background 0.5s ease;
}
body.normal {
background: linear-gradient(
135deg,
hsl(calc(200 + var(--happiness) * 1.2), 80%, calc(30% + var(--happiness) * 0.3%)),
hsl(calc(220 + var(--happiness) * 1.1), 70%, calc(40% + var(--happiness) * 0.4%))
);
}
body.saddest { background: #444; }
h1 { text-align: center; margin-bottom: 1rem; text-shadow: 0 2px 4px rgba(0,0,0,0.2); }
.container { display: flex; gap: 2rem; max-width: 1000px; width: 100%; }
.controls, .visuals { flex: 1; }
.controls {
background: rgba(255,255,255,0.15); backdrop-filter: blur(10px);
border-radius: 16px; padding: 2rem; box-shadow: 0 8px 32px rgba(0,0,0,0.1);
}
.slider-group { margin-bottom: 1.5rem; }
.label { display: flex; justify-content: space-between; margin-bottom: 0.5rem; }
input[type=range] { width: 100%; height: 8px; appearance: none; background: rgba(255,255,255,0.3); border-radius: 4px; outline: none; }
input[type=range]:disabled { background: rgba(200,200,200,0.3); }
input[type=range]::-webkit-slider-thumb { appearance: none; width: 20px; height: 20px; background: white; border-radius: 50%; cursor: pointer; box-shadow: 0 2px 4px rgba(0,0,0,0.2); }
select { width: 100%; padding: 0.5rem; border-radius: 8px; border: none; }
button { width: 100%; padding: 0.75rem; margin-top: 2rem; border: none; border-radius: 8px; background: white; font-size: 1rem; cursor: pointer; box-shadow: 0 2px 4px rgba(0,0,0,0.2); }
#canvas { width: 100%; height: 240px; margin-top: 1.5rem; }
.flower-container { position: relative; width: 200px; height: 200px; margin: 1.5rem auto; }
.flower { position: absolute; width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; }
.stem { position: absolute; background: linear-gradient(to bottom, #5a8f3d,#3a5e2b); width: 8px; height: 120px; bottom: 0; left: 50%; transform: translateX(-50%); transition: background 0.5s, transform 0.5s; }
.flower.dead .stem { background: gray; transform: translateX(-50%) rotate(45deg); }
.flower.saddest .stem { background: black; transform: translateX(-50%) rotate(60deg); }
.petal { position: absolute; background: currentColor; border-radius: 50% 50% 0 50%; transform-origin: bottom center; opacity: 0; transition: opacity 0.5s ease; }
.happiness-bar { width: 100%; height: 20px; background: rgba(0,0,0,0.1); border-radius: 10px; overflow: hidden; margin-top: 1rem; }
.happiness-fill { height: 100%; width: 0%; background: hsl(200,80%,60%); transition: width 0.5s, background 0.5s; }
</style>
</head>
<body class="normal">
<div class="container">
<div class="controls">
<h1>Rich, Boundary & Exposure Experiment</h1>
<div class="slider-group">
<div class="label">Money: <span id="RVal">0%</span> (<span id="RAmount">€0</span>)</div>
<input type="range" id="R" min="0" max="100" step="1" value="0" />
</div>
<div class="slider-group">
<div class="label">Fame: <span id="FVal">0%</span> (<span id="FCount">0</span> ppl)</div>
<input type="range" id="F" min="0" max="100" step="1" value="0" />
</div>
<div class="slider-group">
<div class="label">Boundaries: <span id="BVal">0.00</span></div>
<input type="range" id="B" min="0" max="1" step="0.01" value="0" />
</div>
<div class="slider-group">
<div class="label">Jurisdiction</div>
<select id="jurisdiction">
<option value="0.6">High Privacy (Cayman)</option>
<option value="0.7">Mod Privacy (Switzerland)</option>
<option value="0.8">Low Privacy (EU)</option>
<option value="1">High Exposure (US)</option>
</select>
</div>
<button id="resetBtn">Reset</button>
<div class="happiness-bar"><div class="happiness-fill" id="happinessFill"></div></div>
<div class="flower-container"><div class="flower" id="flower"><div class="stem"></div></div></div>
</div>
<div class="visuals"><canvas id="canvas"></canvas></div>
</div>
<script>
const R = document.getElementById('R'), F = document.getElementById('F'), B = document.getElementById('B'), Jur = document.getElementById('jurisdiction');
const RVal = document.getElementById('RVal'), FVal = document.getElementById('FVal'), BVal = document.getElementById('BVal');
const RAmount = document.getElementById('RAmount'), FCount = document.getElementById('FCount');
const resetBtn = document.getElementById('resetBtn'), canvas = document.getElementById('canvas'), ctx = canvas.getContext('2d');
const flower = document.getElementById('flower'), happinessFill = document.getElementById('happinessFill'), body = document.body;
const maxMoney=5e9, maxPeople=8e9, basePetals=6, maxRings=5; let prevF=0;
function compute(){
const s=R.value/100, Rnorm=Math.pow(s,3), money=Rnorm*maxMoney;
let sliderF=+F.value; if(sliderF<prevF){sliderF=prevF; F.value=sliderF;} const moneyF=Rnorm*100;
const actualF=Math.max(sliderF, moneyF); prevF=actualF;
const fame=actualF/100, people=Math.round(fame*maxPeople);
let Binput=+B.value; if(R.value==0){Binput=0; B.disabled=true;} else B.disabled=false;
const boundaryCost=Binput*Math.pow(fame,2);
const RnormEff=Math.max(0,Rnorm*(1-boundaryCost));
const effectiveB=Binput*RnormEff;
const jur=+Jur.value;
const Enorm=fame*(1-effectiveB)*(1-effectiveB)*jur;
const U_money=Math.sqrt(RnormEff), U_bound=effectiveB, pen_exposure=Math.pow(Enorm,1.2);
let Hraw=U_money+U_bound-pen_exposure;
let Hnorm=Math.max(0,Math.min(1,(Hraw+0.5)/1.5));
const Hperc=Hnorm*100;
// dynamic money slider max
const newMax=Math.max(5, 100*(1-Hnorm*0.5)); R.max=newMax;
return {RnormEff,actualF,people,effectiveB,Enorm,boundaryCost,Hperc,Hnorm};
}
function draw(){
const {RnormEff,actualF,people,effectiveB,Enorm,boundaryCost,Hperc,Hnorm}=compute();
RVal.textContent=`${Math.round(R.value)}%`;
FVal.textContent=`${actualF.toFixed(0)}%`;
FCount.textContent=people.toLocaleString();
BVal.textContent=effectiveB.toFixed(2);
RAmount.textContent=`€${(RnormEff*maxMoney).toLocaleString()}`;
body.className=(R.value==0 && actualF==0)?'saddest':'normal';
body.style.setProperty('--happiness',Hperc);
happinessFill.style.width=`${Hperc}%`;
happinessFill.style.background=`hsl(${Hperc*1.2},80%,60%)`;
flower.classList.toggle('dead',Hperc===0);
flower.querySelectorAll('.petal').forEach(p=>p.remove());
const rings=Math.floor(Hnorm*maxRings);
for(let r=1;r<=rings;r++){
const petalsInRing=r*basePetals, radius=30+r*20;
for(let i=0;i<petalsInRing;i++){
const angle=(i/petalsInRing)*360;
const petal=document.createElement('div'); petal.className='petal';
petal.style.width='15px'; petal.style.height='15px';
petal.style.color=`hsl(${Hperc*1.2+(r-1)*30},80%,60%)`;
petal.style.transform=`rotate(${angle}deg) translateY(-${radius}px) rotate(-${angle}deg)`;
petal.style.opacity=Hnorm;
flower.appendChild(petal);
}
}
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.font='16px Arial'; ctx.fillStyle='#000';
ctx.fillText(`Money Util √R: ${Math.sqrt(RnormEff).toFixed(2)}`,20,30);
ctx.fillText(`Boundary Util: ${effectiveB.toFixed(2)}`,20,55);
ctx.fillText(`Boundary Cost: ${boundaryCost.toFixed(2)}`,20,80);
ctx.fillText(`Exposure Penalty: ${Enorm.toFixed(2)}`,20,105);
ctx.fillText(`Happiness: ${Hperc.toFixed(1)}%`,20,130);
ctx.fillStyle='rgba(0,0,0,0.1)'; ctx.fillRect(20,150,460,20);
ctx.fillStyle=`hsl(${Hperc*1.2},80%,60%)`; ctx.fillRect(20,150,(Hperc/100)*460,20);
ctx.fillStyle='#000'; ctx.font='14px "Segoe UI"'; ctx.fillText('Low H',20,185); ctx.fillText('High H',460,185);
}
[R,F,B,Jur].forEach(el=>el.addEventListener('input',draw));
resetBtn.addEventListener('click',()=>{R.value=0;F.value=0;B.value=0;Jur.value='0.6';prevF=0;draw();});
draw();
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=web3district/happy-combo" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>