pupilometer/src/controllerSoftware/templates/index.html

328 lines
14 KiB
HTML

<!DOCTYPE html>
<html>
<head>
<title>RGB Lamp Matrix Control</title>
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script>
// === Client-Side State and Helper Functions ===
/* var clientMatrix = [
[{% for col in range(5) %}'{{ matrix[0][col] }}'{% if not loop.last %}, {% endif %}{% endfor %}],
[{% for col in range(5) %}'{{ matrix[1][col] }}'{% if not loop.last %}, {% endif %}{% endfor %}],
[{% for col in range(5) %}'{{ matrix[2][col] }}'{% if not loop.last %}, {% endif %}{% endfor %}],
[{% for col in range(5) %}'{{ matrix[3][col] }}'{% if not loop.last %}, {% endif %}{% endfor %}],
[{% for col in range(5) %}'{{ matrix[4][col] }}'{% if not loop.last %}, {% endif %}{% endfor %}]
];*/
var clientMatrix = [
{% for row in matrix %}
[{% for color in row %}'{{ color }}'{% if not loop.last %}, {% endif %}{% endfor %}]{% if not loop.last %}, {% endif %}
{% endfor %}
];
var selectedLamps = [];
const matrixSize = 5;
const centerCoords = {row: Math.floor(matrixSize / 2), col: Math.floor(matrixSize / 2)};
const white3000k = {r: 255, g: 180, b: 100};
const white6500k = {r: 200, g: 220, b: 255};
const blue = {r: 0, g: 0, b: 255};
function hexToRgb(hex) {
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result ? {
r: parseInt(result[1], 16),
g: parseInt(result[2], 16),
b: parseInt(result[3], 16)
} : {r: 0, g: 0, b: 0};
}
function getMixedColor(w3k, w6k, b) {
let final_r = Math.min(255, Math.round((w3k / 255 * white3000k.r) + (w6k / 255 * white6500k.r)));
let final_g = Math.min(255, Math.round((w3k / 255 * white3000k.g) + (w6k / 255 * white6500k.g)));
let final_b = Math.min(255, Math.round((w3k / 255 * white3000k.b) + (w6k / 255 * white6500k.b) + (b / 255 * blue.b)));
let hex = '#' + ('0' + final_r.toString(16)).slice(-2) + ('0' + final_g.toString(16)).slice(-2) + ('0' + final_b.toString(16)).slice(-2);
return {r: final_r, g: final_g, b: final_b, hex: hex};
}
// CORRECTED: Dynamic Region Mapping Functions
function getUpperRegion(n) {
let region = [];
for (let r = 0; r < n; r++) {
for (let c = 0; c < n; c++) {
// Correctly includes all lamps in the upper half of the grid
if (r < centerCoords.row) {
region.push({row: r, col: c});
}
}
}
return region;
}
function getLowerRegion(n) {
let region = [];
for (let r = 0; r < n; r++) {
for (let c = 0; c < n; c++) {
// Correctly includes all lamps in the lower half of the grid
if (r > centerCoords.row) {
region.push({row: r, col: c});
}
}
}
return region;
}
function getLeftRegion(n) {
let region = [];
for (let r = 0; r < n; r++) {
for (let c = 0; c < n; c++) {
// Correctly includes all lamps in the left half of the grid
if (c < centerCoords.col) {
region.push({row: r, col: c});
}
}
}
return region;
}
function getRightRegion(n) {
let region = [];
for (let r = 0; r < n; r++) {
for (let c = 0; c < n; c++) {
// Correctly includes all lamps in the right half of the grid
if (c > centerCoords.col) {
region.push({row: r, col: c});
}
}
}
return region;
}
function getInnerRing(n) {
let region = [];
let start = centerCoords.row - 1;
let end = centerCoords.row + 1;
for (let r = start; r <= end; r++) {
for (let c = start; c <= end; c++) {
if (r !== centerCoords.row || c !== centerCoords.col) {
region.push({row: r, col: c});
}
}
}
return region;
}
function getOuterRing(n) {
let region = [];
for (let r = 0; r < n; r++) {
for (let c = 0; c < n; c++) {
if (r === 0 || r === n - 1 || c === 0 || c === n - 1) {
region.push({row: r, col: c});
}
}
}
return region;
}
function renderMatrix() {
for (let r = 0; r < 5; r++) {
for (let c = 0; c < 5; c++) {
let lampElement = $(`.lamp[data-row="${r}"][data-col="${c}"]`);
let color = clientMatrix[r][c];
let isSelected = selectedLamps.some(lamp => lamp.row === r && lamp.col === c);
lampElement.css('background-color', color);
if (isSelected) {
lampElement.addClass('selected');
} else {
lampElement.removeClass('selected');
}
if (color !== '#000000') {
lampElement.addClass('on');
lampElement.css('box-shadow', `0 0 15px ${color}, 0 0 25px ${color}`);
} else {
lampElement.removeClass('on');
lampElement.css('box-shadow', 'inset 0 0 5px rgba(0,0,0,0.5)');
}
}
}
}
function updateSlidersFromColor(targetColor) {
let rgb = hexToRgb(targetColor);
$('#white-3000k-slider, #white-6500k-slider, #blue-slider').val(0);
$('#white-3000k-value, #white-6500k-value, #blue-value').val(0);
}
// === Event Handlers ===
$(document).ready(function() {
renderMatrix();
var regionMaps = {
'Upper': getUpperRegion(matrixSize),
'Lower': getLowerRegion(matrixSize),
'Left': getLeftRegion(matrixSize),
'Right': getRightRegion(matrixSize),
'Inner ring': getInnerRing(matrixSize),
'Outer ring': getOuterRing(matrixSize)
};
$('.region-button').on('click', function() {
var region = $(this).data('region');
selectedLamps = regionMaps[region];
if (selectedLamps.length > 0) {
$('.control-panel').show();
$('.region-slider-group input').prop('disabled', false);
updateSlidersFromColor(clientMatrix[selectedLamps[0].row][selectedLamps[0].col]);
} else {
$('.control-panel').hide();
$('.region-slider-group input').prop('disabled', true);
}
renderMatrix();
});
$('.region-slider-group input[type="range"]').on('input', function() {
if (selectedLamps.length === 0) return;
var w3k = $('#white-3000k-slider').val();
var w6k = $('#white-6500k-slider').val();
var b = $('#blue-slider').val();
$('#white-3000k-value').val(w3k);
$('#white-6500k-value').val(w6k);
$('#blue-value').val(b);
var finalColor = getMixedColor(w3k, w6k, b);
let centerColor = clientMatrix[centerCoords.row][centerCoords.col];
for (let r = 0; r < 5; r++) {
for (let c = 0; c < 5; c++) {
if (r === centerCoords.row && c === centerCoords.col) continue;
clientMatrix[r][c] = '#000000';
}
}
selectedLamps.forEach(lamp => {
clientMatrix[lamp.row][lamp.col] = finalColor.hex;
});
var data = {
lamps: selectedLamps,
r: finalColor.r,
g: finalColor.g,
b: finalColor.b
};
$.ajax({ url: '/set_color', type: 'POST', contentType: 'application/json', data: JSON.stringify(data) });
renderMatrix();
});
$('.region-slider-group input[type="number"]').on('input', function() {
var value = parseInt($(this).val());
if (isNaN(value) || value < 0) value = 0;
if (value > 255) value = 255;
$(this).val(value);
$(this).siblings('input[type="range"]').val(value).trigger('input');
});
$('.center-slider-group input[type="range"]').on('input', function() {
var w3k = $('#center-white-3000k-slider').val();
var w6k = $('#center-white-6500k-slider').val();
var b = $('#center-blue-slider').val();
$('#center-white-3000k-value').val(w3k);
$('#center-white-6500k-value').val(w6k);
$('#center-blue-value').val(b);
var finalColor = getMixedColor(w3k, w6k, b);
clientMatrix[centerCoords.row][centerCoords.col] = finalColor.hex;
var data = {
lamps: [{row: 2, col: 2}],
r: finalColor.r,
g: finalColor.g,
b: finalColor.b
};
$.ajax({ url: '/set_color', type: 'POST', contentType: 'application/json', data: JSON.stringify(data) });
renderMatrix();
});
$('.center-slider-group input[type="number"]').on('input', function() {
var value = parseInt($(this).val());
if (isNaN(value) || value < 0) value = 0;
if (value > 255) value = 255;
$(this).val(value);
$(this).siblings('input[type="range"]').val(value).trigger('input');
});
});
</script>
</head>
<body>
<div class="container">
<h1>RGB Lamp Matrix Control</h1>
<div class="region-control">
<button class="region-button" data-region="Upper">Upper</button>
<button class="region-button" data-region="Lower">Lower</button>
<button class="region-button" data-region="Left">Left</button>
<button class="region-button" data-region="Right">Right</button>
<button class="region-button" data-region="Inner ring">Inner ring</button>
<button class="region-button" data-region="Outer ring">Outer ring</button>
</div>
<div class="matrix-grid">
{% for row in range(5) %}
{% for col in range(5) %}
<div class="lamp" data-row="{{ row }}" data-col="{{ col }}" style="background-color: {{ matrix[row][col] }}; box-shadow: {{ '0 0 15px ' + matrix[row][col] + ', 0 0 25px ' + matrix[row][col] if matrix[row][col] != '#000000' else 'inset 0 0 5px rgba(0,0,0,0.5)' }}"></div>
{% endfor %}
{% endfor %}
</div>
<div class="center-lamp-control">
<h2>Center Lamp</h2>
<div class="slider-group center-slider-group">
<div class="slider-row">
<span class="slider-label">White 3000K</span>
<input type="range" id="center-white-3000k-slider" class="white-3000k" min="0" max="255" value="0">
<input type="number" id="center-white-3000k-value" min="0" max="255" value="0">
</div>
<div class="slider-row">
<span class="slider-label">White 6500K</span>
<input type="range" id="center-white-6500k-slider" class="white-6500k" min="0" max="255" value="0">
<input type="number" id="center-white-6500k-value" min="0" max="255" value="0">
</div>
<div class="slider-row">
<span class="slider-label">Blue</span>
<input type="range" id="center-blue-slider" class="blue" min="0" max="255" value="0">
<input type="number" id="center-blue-value" min="0" max="255" value="0">
</div>
</div>
</div>
<div class="control-panel">
<h2>Region</h2>
<div class="slider-group region-slider-group">
<div class="slider-row">
<span class="slider-label">White 3000K</span>
<input type="range" id="white-3000k-slider" class="white-3000k" min="0" max="255" value="0" disabled>
<input type="number" id="white-3000k-value" min="0" max="255" value="0" disabled>
</div>
<div class="slider-row">
<span class="slider-label">White 6500K</span>
<input type="range" id="white-6500k-slider" class="white-6500k" min="0" max="255" value="0" disabled>
<input type="number" id="white-6500k-value" min="0" max="255" value="0" disabled>
</div>
<div class="slider-row">
<span class="slider-label">Blue</span>
<input type="range" id="blue-slider" class="blue" min="0" max="255" value="0" disabled>
<input type="number" id="blue-value" min="0" max="255" value="0" disabled>
</div>
</div>
</div>
</div>
</body>
</html>