6 Commits

Author SHA1 Message Date
4cc6b7e9d8 lab 6 done 2025-12-29 00:03:52 +10:00
73ea28eab6 finished table controls 2025-12-12 11:35:56 +10:00
ea0b091c8a table added 2025-12-12 10:57:38 +10:00
c53abdb678 added table controls 2025-12-12 10:10:30 +10:00
2b4a36c1ff details BEM 2025-12-11 22:26:18 +10:00
03e7b28167 details page in progress 2025-12-11 21:58:56 +10:00
15 changed files with 644 additions and 277 deletions

19
labs/lab6/lab6.js Normal file
View File

@@ -0,0 +1,19 @@
function areNumbersEqual(num1,num2,percision){
return Math.abs(num1 - num2) < percision;
}
func=(...args) => {
const percision=0.1E-2;
args.sort();
let out = "";
let lastElem = null;
for (let i = 0; i < args.length-1; i++){
if (areNumbersEqual(args[i],args[i+1],percision) && (!areNumbersEqual(args[i],lastElem,percision) || lastElem === null)){
lastElem = args[i];
out += lastElem+" ";
}
}
return out;
}
console.log(func(-0.0009111,0,-0.0009111,-0.009111,-0,1.1,1.101,2.0001,2))

17
lectures/temp.js Normal file
View File

@@ -0,0 +1,17 @@
function updateDict(dict, update) {
let key, value = update.entries()[0];
dict[key] = value + (key in dict) ? dict[key] : 0;
}
aboba={"asd":123}
upd={"asd":123}
upd1={"asd":123}
updateDict(aboba,upd1)
console.log(aboba)
updateDict(aboba,upd1)
console.log(aboba)

57
package-lock.json generated
View File

@@ -713,11 +713,10 @@
} }
}, },
"node_modules/acorn": { "node_modules/acorn": {
"version": "4.0.13", "version": "8.15.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
"integrity": "sha512-fu2ygVGuMmlzG8ZeRJ0bvR41nsAkxxhbyk8bZ1SS521Z7vmgJFTQQlfz/Mp/nJexGBz+v8sC9bM6+lNgskt4Ug==", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"dev": true, "dev": true,
"license": "MIT",
"bin": { "bin": {
"acorn": "bin/acorn" "acorn": "bin/acorn"
}, },
@@ -735,6 +734,18 @@
"acorn": "^4.0.4" "acorn": "^4.0.4"
} }
}, },
"node_modules/acorn-globals/node_modules/acorn": {
"version": "4.0.13",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz",
"integrity": "sha512-fu2ygVGuMmlzG8ZeRJ0bvR41nsAkxxhbyk8bZ1SS521Z7vmgJFTQQlfz/Mp/nJexGBz+v8sC9bM6+lNgskt4Ug==",
"dev": true,
"bin": {
"acorn": "bin/acorn"
},
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/acorn-import-phases": { "node_modules/acorn-import-phases": {
"version": "1.0.4", "version": "1.0.4",
"resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz", "resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz",
@@ -3261,6 +3272,18 @@
"object-assign": "^4.0.1" "object-assign": "^4.0.1"
} }
}, },
"node_modules/is-expression/node_modules/acorn": {
"version": "4.0.13",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz",
"integrity": "sha512-fu2ygVGuMmlzG8ZeRJ0bvR41nsAkxxhbyk8bZ1SS521Z7vmgJFTQQlfz/Mp/nJexGBz+v8sC9bM6+lNgskt4Ug==",
"dev": true,
"bin": {
"acorn": "bin/acorn"
},
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/is-extglob": { "node_modules/is-extglob": {
"version": "2.1.1", "version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
@@ -5861,19 +5884,6 @@
} }
} }
}, },
"node_modules/terser/node_modules/acorn": {
"version": "8.15.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"dev": true,
"license": "MIT",
"bin": {
"acorn": "bin/acorn"
},
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/terser/node_modules/commander": { "node_modules/terser/node_modules/commander": {
"version": "2.20.3", "version": "2.20.3",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
@@ -6375,19 +6385,6 @@
"node": ">=10.13.0" "node": ">=10.13.0"
} }
}, },
"node_modules/webpack/node_modules/acorn": {
"version": "8.15.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"dev": true,
"license": "MIT",
"bin": {
"acorn": "bin/acorn"
},
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/websocket-driver": { "node_modules/websocket-driver": {
"version": "0.7.4", "version": "0.7.4",
"resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz",

View File

@@ -1,124 +1,306 @@
block variables
- -
var navbarItems = {
// Данные для меню навигации
var menuItems = {
Home: './index.html', Home: './index.html',
Embedded: './embeded_details.html', Embedded: './embeded_details.html',
OpenCV: './opencv_details.html', OpenCV: './opencv_details.html',
Photography: './photography_details.html', Photography: './photography-details.html',
Table: './table.html', Table: './table.html',
Institute: './images/institute.png' Institute: './images/institute.png'
}; };
// Данные для боковых карточек
var smallCards = [ var smallCards = [
{ {
header: 'Заголовок', header: 'Заголовок',
text: '3D printers are versatile tools used for creating prototypes, custom parts, and artistic designs. They work by layering materials.', text: '3D printers are versatile tools used for creating prototypes, custom parts, and artistic designs. They work by layering materials.',
image: '../images/16x10/3d-printer.jpeg', image: require('../images/16x10/3d-printer.jpeg'),
imageAlt: '3D Printer', imageAlt: '3D Printer',
link: '#', link: '#',
}, },
{ {
header: 'BLHeli ESCs', header: 'BLHeli ESCs',
text: 'BLHeli ESCs are electronic speed controllers designed for drones, offering smooth and precise motor control.', text: 'BLHeli ESCs are electronic speed controllers designed for drones, offering smooth and precise motor control.',
image: '../images/16x10/blheli-esc.jpeg', image: require('../images/16x10/blheli-esc.jpeg'),
imageAlt: 'BLHeli ESC', imageAlt: 'BLHeli ESC',
link: '#', link: '#',
}, },
{ {
header: 'Raspberry Pi Nano', header: 'Raspberry Pi Nano',
text: 'Raspberry Pi Nano is a compact computer ideal for learning, prototyping, and IoT projects. It is highly energy-efficient.', text: 'Raspberry Pi Nano is a compact computer ideal for learning, prototyping, and IoT projects. It is highly energy-efficient.',
image: '../images/16x10/rpi-nano.jpeg', image: require('../images/16x10/rpi-nano.jpeg'),
imageAlt: 'Raspberry Pi Nano', imageAlt: 'Raspberry Pi Nano',
link: '#', link: '#',
}, },
{ {
header: 'Smart Thermostats', header: 'Smart Thermostats',
text: 'Smart thermostats help regulate home temperatures efficiently, saving energy and enhancing comfort with automation.', text: 'Smart thermostats help regulate home temperatures efficiently, saving energy and enhancing comfort with automation.',
image: '../images/16x10/thermostat.jpeg', image: require('../images/16x10/thermostat.jpeg'),
imageAlt: 'Smart Thermostat', imageAlt: 'Smart Thermostat',
link: '#', link: '#',
} }
]; ];
const pages = { var galleryImages= [
embedded: { { src: require('../images/sqarucos.png'), alt: 'ESP32'},
title: 'Embedded Details', { src: require('../images/sqstm32.png'), alt: 'Arduino'},
slug: 'embedded', { src: require('../images/sqesp32.png'), alt: 'STM32'}
menuTitle: 'Embeded Details', ];
images: [
{ src: './images/esp32.png', alt: 'ESP32', height: 150 }, var locationFilters = [
{ src: './images/arduino.png', alt: 'Arduino', height: 150 }, { id: 'loc_kitchen', value: 'Kitchen', label: 'Kitchen' },
{ src: './images/stm32.png', alt: 'STM32', height: 150 } { id: 'loc_living', value: 'Living Room', label: 'Living Room' },
], { id: 'loc_balcony', value: 'Balcony', label: 'Balcony' },
paragraphs: [ { id: 'loc_bedroom', value: 'Bedroom', label: 'Bedroom' }
"My programming path started with embeded systems, i love all the low level things that Mcu could do with just a little bit of code, sometimes build or flashing progress could take some time to get a hand of , but after that everething usualy goes smooth", ];
"The first MCU i tried was a ATmega328P, after some time i was surprised with the debug capabilities on the Stm32 and now i'm working with esp32-s3 , that's a good chip, has internal JTAG and all the shiny wireless interfaces but feels faulty for some reason <i>regular segfaults with CDC</i>"
], var sensorTypeFilters = [
table: { { id: 'type_xiaomi', value: 'Xiaomi', label: 'Xiaomi' },
title: 'Microcontroller Comparison Table', { id: 'type_bmp220', value: 'Bmp220', label: 'Bmp220' },
headers: ['Board/MCU', 'UART Count', 'Dynamic UART Assignment', 'ADC Channels', 'Debug Support', 'Flash Size', 'Wireless Connectivity'], { id: 'type_scd30', value: 'Scd30(Internal)', label: 'Scd30(Internal)' },
rows: [ { id: 'type_bmp280', value: 'Bmp280', label: 'Bmp280' }
['ESP32', '3', 'Yes (via IO MUX)', '18', 'JTAG, Serial', '4MB (typical)', 'Wi-Fi, Bluetooth'], ];
['ESP32-S3', '3', 'Yes (via IO MUX)', '20', 'JTAG, Serial', '8MB (typical)', 'Wi-Fi, Bluetooth LE'],
['ESP-01', '1', 'No', '1', 'Serial only', '512KB/1MB', 'Wi-Fi'], var sortOptions = [
['Arduino Uno (ATmega328P)', '1', 'No', '6', 'Serial, DebugWire', '32KB', 'None'], { value: '', label: '-- None --' },
['Blue Pill (STM32F103C8T6)', '3', 'Yes (remappable)', '10', 'SWD, Serial', '64KB/128KB', 'None'] { value: 'SensorID', label: 'SensorID' },
] { value: 'Timestamp', label: 'Time' },
}, { value: 'BatteryLevel', label: 'BatteryLevel' },
footer: "no rpi pico here , the build system has won over my temper" { value: 'Temperature', label: 'Temperature' },
}, { value: 'Humidity', label: 'Humidity' }
];
opencv: {
title: 'OpenCV Details', var axisOptions = [
slug: 'opencv', { id: 'x_time', value: 'Time', label: 'Time', checked: true },
menuTitle: 'OpenCV Details', { id: 'x_battery', value: 'BatteryLevel', label: 'BatteryLevel', checked: false },
images: [ { id: 'x_temperature', value: 'Temperature', label: 'Temperature', checked: false },
{ src: './images/opencv.png', alt: 'OpenCV', height: 150 } { id: 'x_humidity', value: 'Humidity', label: 'Humidity', checked: false }
], ];
paragraphs: [
"as mentioned before i love when programs are able to <i>see</i> things", var valueOptions = [
"my experience with opencv started with simple hight level functions like detectCircle or findContours and etc...", { id: 'val_temperature', value: 'AverageTemperature', label: 'Average Temperature', checked: true },
"Right now i'm crawling deeper into the library , and the idea of standartisation of parameters between different cameras is appealig to me", { id: 'val_humidity', value: 'Humidity', label: 'Average Humidity', checked: false },
"so i'm trying to understand how all that works from the math side", { id: 'val_battery', value: 'BatteryLevel', label: 'Average BatteryLevel', checked: false }
"Additionally, I'm exploring Re-Identification (ReId) techniques, they are used for recognizing and tracking objects across different camera views or consecutive frames." ]
],
content: { var sensorData = [
type: 'text', {
text: "One of many projects I've worked on is <a href=\"https://github.com/OkunElya/ArucoNGP-MapCreator\" target=\"_blank\">ArucoNGP-MapCreator</a>.<br>The idea was to create a relative map of Aruco markers just from photos of pairs (or more) of them.<br>It can also estimate the camera's position in the world relative to a specific marker, using only images containing any marker.<br>It was also my first deep dive into linear algebra." sensorId: 'TEMP-001',
} location: 'Balcony',
}, timestamp: '2025-10-03T03:41:50Z',
temperature: 19.4,
photography: { tempDifference: -0.2,
title: 'Photography Details', sensorType: 'Bmp220',
slug: 'photography', batteryLevel: 95,
menuTitle: 'Photography Details', humidity: 38.1,
images: [], lastCalibrationDate: '2025-07-26'
paragraphs: [ },
"Usually i capture landcape scenes with SLR camera, the main workhorse is Nikon D3100 with kit and 70-210mm" {
], sensorId: 'TEMP-003',
gallery: [ location: 'Bedroom',
[ timestamp: '2025-10-03T03:42:46Z',
{ src: 'images/photos/image0.png', alt: 'Photo 0', width: 200 }, temperature: 18.2,
{ src: 'images/photos/image1.png', alt: 'Photo 1', width: 200 }, tempDifference: -0.1,
{ src: 'images/photos/image2.png', alt: 'Photo 2', width: 200 } sensorType: 'Xiaomi',
], batteryLevel: 75,
[ humidity: 45.5,
{ src: 'images/photos/image3.png', alt: 'Photo 3', width: 200 }, lastCalibrationDate: '2025-07-21'
{ src: 'images/photos/image4.png', alt: 'Photo 4', width: 200 }, },
{ src: 'images/photos/image5.png', alt: 'Photo 5', width: 200 } {
] sensorId: 'TEMP-004',
] location: 'Balcony',
} timestamp: '2025-10-03T03:43:48Z',
}; temperature: 24.1,
tempDifference: 0.1,
- sensorType: 'Xiaomi',
const menu = [ batteryLevel: 72,
{ href: './index.html', title: 'Home' }, humidity: 50.5,
{ href: './embeded_details.html', title: 'Embeded Details' }, lastCalibrationDate: '2025-08-30'
{ href: './opencv_details.html', title: 'OpenCV Details' }, },
{ href: './photography_details.html', title: 'Photography Details' }, {
{ href: './table.html', title: 'Table with filters (not working yet)' }, sensorId: 'TEMP-001',
{ href: './images/institute.png', title: 'Institute' } location: 'Balcony',
timestamp: '2025-10-03T03:44:34Z',
temperature: 19.1,
tempDifference: -0.3,
sensorType: 'Bmp220',
batteryLevel: 95,
humidity: 56.5,
lastCalibrationDate: '2025-07-26'
},
{
sensorId: 'TEMP-006',
location: 'Kitchen',
timestamp: '2025-10-03T03:45:46Z',
temperature: 22.8,
tempDifference: 0.0,
sensorType: 'Scd30(Internal)',
batteryLevel: 80,
humidity: 41.4,
lastCalibrationDate: '2025-09-10'
},
{
sensorId: 'TEMP-010',
location: 'Balcony',
timestamp: '2025-10-03T03:46:18Z',
temperature: 21.7,
tempDifference: 0.5,
sensorType: 'Scd30(Internal)',
batteryLevel: 79,
humidity: 59.8,
lastCalibrationDate: '2025-08-07'
},
{
sensorId: 'TEMP-006',
location: 'Balcony',
timestamp: '2025-10-03T03:47:05Z',
temperature: 22.7,
tempDifference: -0.1,
sensorType: 'Scd30(Internal)',
batteryLevel: 80,
humidity: 36.1,
lastCalibrationDate: '2025-09-10'
},
{
sensorId: 'TEMP-006',
location: 'Bedroom',
timestamp: '2025-10-03T03:48:13Z',
temperature: 22.9,
tempDifference: 0.2,
sensorType: 'Scd30(Internal)',
batteryLevel: 80,
humidity: 56.1,
lastCalibrationDate: '2025-09-10'
},
{
sensorId: 'TEMP-005',
location: 'Living Room',
timestamp: '2025-10-03T03:49:03Z',
temperature: 24.4,
tempDifference: 0.4,
sensorType: 'Bmp180',
batteryLevel: 91,
humidity: 30.1,
lastCalibrationDate: '2025-08-07'
},
{
sensorId: 'TEMP-001',
location: 'Kitchen',
timestamp: '2025-10-03T03:50:24Z',
temperature: 19.1,
tempDifference: 0.0,
sensorType: 'Bmp220',
batteryLevel: 95,
humidity: 64.8,
lastCalibrationDate: '2025-07-26'
},
{
sensorId: 'TEMP-008',
location: 'Living Room',
timestamp: '2025-10-03T03:51:12Z',
temperature: 21.9,
tempDifference: -0.1,
sensorType: 'Scd30(Internal)',
batteryLevel: 92,
humidity: 36.0,
lastCalibrationDate: '2025-08-02'
},
{
sensorId: 'TEMP-009',
location: 'Balcony',
timestamp: '2025-10-03T03:51:46Z',
temperature: 22.3,
tempDifference: 0.0,
sensorType: 'Xiaomi',
batteryLevel: 76,
humidity: 74.0,
lastCalibrationDate: '2025-09-17'
},
{
sensorId: 'TEMP-003',
location: 'Kitchen',
timestamp: '2025-10-03T03:52:23Z',
temperature: 18.4,
tempDifference: 0.2,
sensorType: 'Xiaomi',
batteryLevel: 75,
humidity: 45.2,
lastCalibrationDate: '2025-07-21'
},
{
sensorId: 'TEMP-010',
location: 'Living Room',
timestamp: '2025-10-03T03:53:44Z',
temperature: 21.8,
tempDifference: 0.1,
sensorType: 'Scd30(Internal)',
batteryLevel: 79,
humidity: 36.3,
lastCalibrationDate: '2025-08-07'
},
{
sensorId: 'TEMP-001',
location: 'Kitchen',
timestamp: '2025-10-03T03:54:46Z',
temperature: 18.7,
tempDifference: -0.4,
sensorType: 'Bmp220',
batteryLevel: 95,
humidity: 44.3,
lastCalibrationDate: '2025-07-26'
},
{
sensorId: 'TEMP-006',
location: 'Bedroom',
timestamp: '2025-10-03T03:55:24Z',
temperature: 23.3,
tempDifference: 0.4,
sensorType: 'Scd30(Internal)',
batteryLevel: 80,
humidity: 55.9,
lastCalibrationDate: '2025-09-10'
},
{
sensorId: 'TEMP-002',
location: 'Kitchen',
timestamp: '2025-10-03T03:55:57Z',
temperature: 17.7,
tempDifference: -0.5,
sensorType: 'Scd30(Internal)',
batteryLevel: 93,
humidity: 70.2,
lastCalibrationDate: '2025-08-30'
},
{
sensorId: 'TEMP-002',
location: 'Balcony',
timestamp: '2025-10-03T03:57:05Z',
temperature: 17.4,
tempDifference: -0.3,
sensorType: 'Scd30(Internal)',
batteryLevel: 93,
humidity: 66.7,
lastCalibrationDate: '2025-08-30'
},
{
sensorId: 'TEMP-009',
location: 'Living Room',
timestamp: '2025-10-03T03:58:28Z',
temperature: 22.6,
tempDifference: 0.3,
sensorType: 'Xiaomi',
batteryLevel: 76,
humidity: 56.4,
lastCalibrationDate: '2025-09-17'
},
{
sensorId: 'TEMP-004',
location: 'Bedroom',
timestamp: '2025-10-03T03:59:51Z',
temperature: 24.3,
tempDifference: 0.2,
sensorType: 'Xiaomi',
batteryLevel: 72,
humidity: 47.3,
lastCalibrationDate: '2025-08-30'
}
]; ];

View File

@@ -0,0 +1,24 @@
include mixins.pug
html
head
meta(charset="UTF-8")
block title
title Details Page
body
block navbar
+navbarMixin("")
.details
header.details__header
block header
h1 Default Header
.details__content
.details__text
block text
p Default text content
.details__gallery
block gallery
p No images available

View File

@@ -1,60 +1,13 @@
include data.pug include data.pug
-
// Данные для меню навигации
const navbarItems = {
Home: './index.html',
Embedded: './embeded_details.html',
OpenCV: './opencv_details.html',
Photography: './photography_details.html',
Table: './table.html',
Institute: './images/institute.png'
};
const smallCards = [
{
header: 'Заголовок',
text: '3D printers are versatile tools used for creating prototypes, custom parts, and artistic designs. They work by layering materials.',
image: require('../images/16x10/3d-printer.jpeg'),
imageAlt: '3D Printer',
link: '#',
},
{
header: 'BLHeli ESCs',
text: 'BLHeli ESCs are electronic speed controllers designed for drones, offering smooth and precise motor control.',
image: require('../images/16x10/blheli-esc.jpeg'),
imageAlt: 'BLHeli ESC',
link: '#',
},
{
header: 'Raspberry Pi Nano',
text: 'Raspberry Pi Nano is a compact computer ideal for learning, prototyping, and IoT projects. It is highly energy-efficient.',
image: require('../images/16x10/rpi-nano.jpeg'),
imageAlt: 'Raspberry Pi Nano',
link: '#',
},
{
header: 'Smart Thermostats',
text: 'Smart thermostats help regulate home temperatures efficiently, saving energy and enhancing comfort with automation.',
image: require('../images/16x10/thermostat.jpeg'),
imageAlt: 'Smart Thermostat',
link: '#',
}
];
const galleryImages= [
{ src: require('../images/sqarucos.png'), alt: 'ESP32'},
{ src: require('../images/sqstm32.png'), alt: 'Arduino'},
{ src: require('../images/sqesp32.png'), alt: 'STM32'}
]
mixin navbarMixin(selectedItem) mixin navbarMixin(selectedItem)
.navbar .navbar
each navbarUrl,navbarName in navbarItems each navbarUrl,navbarName in navbarItems
if navbarName == selectedItem if navbarName == selectedItem
a.navbar__link__wrapper(href=navbarUrl) a.navbar__link-wrapper(href=navbarUrl)
.navbar__item.navbar__item_selected #{navbarName} .navbar__item.navbar__item_selected #{navbarName}
else else
a.navbar__link__wrapper(href=navbarUrl) a.navbar__link-wrapper(href=navbarUrl)
.navbar__item #{navbarName} .navbar__item #{navbarName}
mixin infoCardsMinxin() mixin infoCardsMinxin()
@@ -70,3 +23,136 @@ mixin infoCardsMinxin()
mixin galleryMixin() mixin galleryMixin()
each img in galleryImages each img in galleryImages
img.gallery__image(src=img.src alt=img.alt) img.gallery__image(src=img.src alt=img.alt)
mixin filtersMixin()
details.filters
summary.filters__summary Filters
form.filters__form
fieldset.filters__fieldset
.filter-group
i.filter-group__label
b Location
br
.filter-group__items
each filter in locationFilters
input.filter-group__checkbox(type="checkbox" id=filter.id name="location" value=filter.value)
span #{filter.label}
br
.filter-group
i.filter-group__label
b Sensor Type
br
.filter-group__items
each filter in sensorTypeFilters
input.filter-group__checkbox(type="checkbox" id=filter.id name="sensor_type" value=filter.value)
span #{filter.label}
br
.filter-group
i.filter-group__label
b Numeric Values
br
.filter-group__range
span Temperature from:
input.filter-group__input(type="number" name="temp_min" placeholder="20")
span to:
input.filter-group__input(type="number" name="temp_max" placeholder="30")
br
span Humidity from:
input.filter-group__input(type="number" name="humidity_min" placeholder="40")
span to:
input.filter-group__input(type="number" name="humidity_max" placeholder="60")
br
.filter-group
i.filter-group__label
b Device Specific Filters
br
.filter-group__items
span Sensor Name:
input.filter-group__input(type="text" name="sensor_name")
br
span Days Since Calibration (max):
input.filter-group__input(type="number" name="calibration_days" placeholder="30")
br
.filter-group
i.filter-group__label
b Measurement Period
br
.filter-group__dates
span From:
input.filter-group__input(type="date" name="date_from")
br
span To:
input.filter-group__input(type="date" name="date_to")
br
.filter-group__buttons
input.filter-group__button.filter-group__button--submit(type="submit" value="Apply Filters")
input.filter-group__button.filter-group__button--reset(type="reset" value="Reset Filters")
mixin sortLevel(level)
.sort-level
i.sort-level__label
b Sort Level #{level}
br
label.sort-level__field-label(for=`sort${level}`) Field:
select.sort-level__select(id=`sort${level}` name=`sort${level}`)
each option in sortOptions
option(value=option.value) #{option.label}
label.sort-level__reverse-label(for=`sort${level}_reverse`)
input.sort-level__checkbox(type="checkbox" id=`sort${level}_reverse` name=`sort${level}_reverse`)
span Reverse
br
if level === '3'
input.sort-level__submit(type="submit" value="Sort")
else
br
mixin sortingMixin()
- const sortLevels = ['1', '2', '3'];
details.sorting
summary.sorting__summary Sortings
form.sorting__form
fieldset.sorting__fieldset
each level in sortLevels
+sortLevel(level)
mixin graphXOption(option)
if option.checked
input.axis-group__radio(type="radio" id=option.id name="x_axis" value=option.value checked)
else
input.axis-group__radio(type="radio" id=option.id name="x_axis" value=option.value)
label.axis-group__option-label(for=option.id) #{option.label}
br
mixin graphYOption(option)
if option.checked
input.values-group__checkbox(type="checkbox" id=option.id name="values" value=option.value checked)
else
input.values-group__checkbox(type="checkbox" id=option.id name="values" value=option.value)
label.values-group__option-label(for=option.id) #{option.label}
br
mixin graphMixin()
details.graph
summary.graph__summary Graph
form.graph__form
fieldset.graph__fieldset
.axis-group
i.axis-group__label
b X axis
br
.axis-group__options
each option in axisOptions
+graphXOption(option)
.values-group
i.values-group__label
b Values
br
.values-group__options
each option in valueOptions
+graphYOption(option)
button.values-group__button(type="submit" id="build_graph" name="build_graph") Build

View File

@@ -1,69 +0,0 @@
include data.pug
mixin detailsPage(pageData)
doctype html
html(lang="en")
head
meta(charset="UTF-8")
title= pageData.title
body(bgcolor="#F0F8FF")
//- Menu
details
summary Menu
ul
each item in menu
li
if item.title === pageData.menuTitle
a(href=item.href)
h4= item.title
else
a(href=item.href)= item.title
//- Page Title
h2(align="center")= pageData.title
hr(width="800" align="center")
//- Header Images
if pageData.images && pageData.images.length > 0
p(align="center")
each img in pageData.images
if img.height
img(src=img.src alt=img.alt height=img.height)
else if img.width
img(src=img.src alt=img.alt width=img.width)
else
img(src=img.src alt=img.alt)
//- Paragraphs
if pageData.paragraphs
each para in pageData.paragraphs
p(align="justify")!= para
//- Table (for embedded page)
if pageData.table
h3(align="center")= pageData.table.title
table(border="1" align="center" cellpadding="6" cellspacing="0")
tr
each header in pageData.table.headers
th= header
each row in pageData.table.rows
tr
each cell in row
td= cell
//- Content (for opencv page)
if pageData.content
hr(width="500" align="center")
p!= pageData.content.text
//- Gallery (for photography page)
if pageData.gallery
each row in pageData.gallery
p(align="center")
each img in row
img(src=img.src alt=img.alt width=img.width)
//- Footer
if pageData.footer
p(align="right")= pageData.footer

View File

@@ -1 +1,3 @@
import './styles/main.styl' import './styles/index.styl'
import './styles/details.styl'
import './styles/table.styl'

View File

@@ -45,7 +45,7 @@ html(lang="en")
img.info-block__image(src=infoBlockB.img alt=infoBlockB.imgAlt) img.info-block__image(src=infoBlockB.img alt=infoBlockB.imgAlt)
.info-block__details .info-block__details
p.info-block__description #{infoBlockB.description} p.info-block__description #{infoBlockB.description}
a.info-block__link(href="#") More info a.info-block__link(href="./photography-details.html") More info
.sidebar .sidebar
+infoCardsMinxin() +infoCardsMinxin()

View File

@@ -0,0 +1,22 @@
extends ../components/details-template.pug
block title
title Photography Portfolio - Details
block navbar
+navbarMixin("Photography")
block header
h1.details__title Photography
p.details__description I prefer landscape photography.
block text
p.details__text-content D3100 -> SLT A58.
block gallery
.details__gallery-item
img.details__gallery-image(src=require('../images/photos/image0.png') alt="Photography 1")
.details__gallery-item
img.details__gallery-image(src=require('../images/photos/image1.png') alt="Photography 2")
.details__gallery-item
img.details__gallery-image(src=require('../images/photos/image2.png') alt="Photography 3")

25
src/pages/table.pug Normal file
View File

@@ -0,0 +1,25 @@
include ../components/mixins.pug
include ../components/data.pug
head
title table
body
+navbarMixin("Table")
.table-controls
+filtersMixin()
+sortingMixin()
+graphMixin()
table.table
tbody.table-content
each dataItem,index in sensorData
if index == 0
tr.table-content__table-header
each value,header in dataItem
th #{header}
tr.table-content__table-row
each value,header in dataItem
td #{value}

58
src/styles/details.styl Normal file
View File

@@ -0,0 +1,58 @@
.details
margin 0 auto
padding 20px
.details__header
margin-bottom 20px
text-align center
.details__title
margin-bottom 5px
.details__description
margin auto
.details__content
display flex
gap 40px
align-items flex-start
.details__text
flex 1
text-align justify
.details__text-content
margin auto 30px
.details__gallery
display flex
flex-direction column
gap 20px
margin auto
.details__gallery-item
overflow hidden
border-radius 8px
box-shadow 0 4px 12px rgba(0, 0, 0, 0.1)
transition transform 0.3s ease, box-shadow 0.3s ease
&:hover
transform translateY(-5px)
box-shadow 0 8px 20px rgba(0, 0, 0, 0.15)
.details__gallery-image
width 100%
height 250px
object-fit cover
display block
@media screen and (max-width: 700px)
.details__content
flex-direction column
.details__gallery
order -1 // Move gallery above text
.details__gallery-image
height 300px

View File

@@ -1,4 +1,5 @@
// Миксины для переиспользования item_h=3em;
double-border() double-border()
border-top double thick silver border-top double thick silver
border-bottom double thick silver border-bottom double thick silver
@@ -18,26 +19,25 @@ grid-responsive(columns)
grid-template-columns columns grid-template-columns columns
grid-template-rows 1fr grid-template-rows 1fr
// Основные стили
.navbar .navbar
double-border() double-border()
font-size 0 font-size 0
grid-responsive(repeat(7, min-content)) grid-responsive(repeat(7, min-content))
justify-items start justify-items start
&__link__wrapper &__link-wrapper
color black color black
text-decoration none text-decoration none
&__item &__item
display inline-block display inline-block
width max-content width max-content
height 3em height item_h
line-height 3em line-height item_h
text-align center text-align center
vertical-align middle vertical-align middle
padding 0 10px padding 0 10px
margin 0 10px margin @padding
overflow hidden overflow hidden
text-overflow ellipsis text-overflow ellipsis
font-size medium font-size medium

View File

@@ -1,2 +0,0 @@
// Импорт стилей для главной страницы
@import 'index.styl'

6
src/styles/table.styl Normal file
View File

@@ -0,0 +1,6 @@
.table, .table-content *, .table-content
border: 1px solid black;
border-collapse: collapse;
.table-content__table-row:nth-child(2n)
background: #F0FFF0;