Javascript-форум (https://javascript.ru/forum/)
-   Элементы интерфейса (https://javascript.ru/forum/dom-window/)
-   -   Время выполнения (https://javascript.ru/forum/dom-window/85735-vremya-vypolneniya.html)

Сергей Ракипов 01.02.2024 10:32

Время выполнения
 
Друзья мне уже стыдно смотреть в глаза GPT но мы ни как не можем понять друг друга.


Есть код который случайно показывает блоки присваивает стили и с ним все нормально. То есть обновил страницу он показал случайный блок, обновил показал и пока все блоки не покажет будет показывать, но это не суть он работает и молодец.

Но нужно что бы возможность увидеть случайный блок была раз в 10 часов. То есть человек зашел на сайт ему показали случайный блок и если он зайдет еще раз или обновит страницу а 10 часов не прошло ему код не отрабатывал свои функции. Прошло 10 часов можно будет показать ему новый случайный блок (ну то есть что бы функции кода отработали) если он зашел или обновил страницу и вот такой интервал так сказать должен блокировать показы, один раз в 10 часов
Плюс если он попытается обновить или зайти в промежуток этих "запрещеных" 10 часов то ему показывали другой блок, а именно блокус классом limitation добавился класс show


вот сам код


// Получаем все блоки и сохраняем их в массив
const blocks = Array.from(document.querySelectorAll('.fact_block'));
// Функция для получения уже показанных блоков из localStorage
function getShownBlocks() {
  const shownBlocks = localStorage.getItem('shownBlocks');
  return shownBlocks ? JSON.parse(shownBlocks) : [];
}
// Функция для сохранения ID показанного блока
function saveShownBlock(blockId) {
  const shownBlocks = getShownBlocks();
  shownBlocks.push(blockId);
  localStorage.setItem('shownBlocks', JSON.stringify(shownBlocks));
  // Проверяем, есть ли у блока класс 'fact_picture_mini_curr'
  if (document.getElementById(blockId).classList.contains('fact_picture_mini_curr')) {
    // Если есть, то сохраняем его в localStorage
    const factPictureMiniCurrIds = JSON.parse(localStorage.getItem('fact_picture_mini_curr')) || [];
    localStorage.setItem('fact_picture_mini_curr', JSON.stringify([...new Set([...factPictureMiniCurrIds, blockId])]));
  }
}
// Функция для удаления класса 'show' у всех блоков
function removeShowClass() {
  blocks.forEach(block => block.classList.remove('show'));
}
// Функция для выбора и показа случайного блока
function showRandomBlock() {
  const shownBlocks = getShownBlocks();
  const availableBlocks = blocks.filter(block => !shownBlocks.includes(block.id) && block.id.includes('fact_'));
  if (availableBlocks.length === 0) {
    // Показываем последний блок, если все остальные уже показаны
    const lastBlock = blocks.find(block => block.id === 'full_collection');
    lastBlock.classList.add('show');
  } else {
    // Выбираем случайный блок из доступных
    const randomBlock = availableBlocks[Math.floor(Math.random() * availableBlocks.length)];
    randomBlock.classList.add('show');
    saveShownBlock(randomBlock.id);
    // Добавляем класс 'fact_picture_mini_curr' к соответствующему блоку с id 'mini_'
    const miniBlock = document.getElementById(`mini_${randomBlock.id.replace('fact_', '')}`);
    if (miniBlock) {
      miniBlock.classList.add('fact_picture_mini_curr');
      saveShownBlock(`mini_${randomBlock.id.replace('fact_', '')}`);
    }
  }
}
// Удаляем класс 'show' у всех блоков и показываем новый блок
removeShowClass();
showRandomBlock();
// Проверяем, есть ли id блока с классом 'fact_picture_mini_curr' в localStorage
const factPictureMiniCurrIds = JSON.parse(localStorage.getItem('fact_picture_mini_curr')) || [];
// Если есть, то добавляем класс 'fact_picture_mini_curr' этим блокам
factPictureMiniCurrIds.forEach(id => {
  document.getElementById(id).classList.add('fact_picture_mini_curr');
});


люди ) помогите если сможете )

ruslan_mart 01.02.2024 12:23

Не проверял, но должно сработать:

function getRandomInt(min, max) {
  return Math.floor(Math.random() * (max - min) + min);
}

const blockList = Array.from(document.querySelectorAll('.fact_block'));
const limitationBlock = document.querySelector('.limitation');

const INTERVAL = 1000 * 60 *  60 * 10; // 10 часов
const STORAGE_KEY = 'random-block';

const currentStorageValue = Number(window.localStorage.getItem(STORAGE_KEY));

if (Number.isNaN(currentStorageValue) || currentStorageValue < Date.now() - INTERVAL) {
  const randomBlockItem = blockList[getRandomInt(0, getRandomInt.length - 1)];
  
  window.localStorage.setItem(STORAGE_KEY, String(Date.now()));
  
  randomBlockItem.classList.add('show');
} else {
  limitationBlock.classList.add('show');
}

Сергей Ракипов 01.02.2024 12:28

Цитата:

Сообщение от ruslan_mart (Сообщение 554660)
Не проверял, но должно сработать:

function getRandomInt(min, max) {
  return Math.floor(Math.random() * (max - min) + min);
}

const blockList = Array.from(document.querySelectorAll('.fact_block'));
const limitationBlock = document.querySelector('.limitation');

const INTERVAL = 1000 * 60 *  60 * 10; // 10 часов
const STORAGE_KEY = 'random-block';

const currentStorageValue = Number(window.localStorage.getItem(STORAGE_KEY));

if (Number.isNaN(currentStorageValue) || currentStorageValue < Date.now() - INTERVAL) {
  const randomBlockItem = blockList[getRandomInt(0, getRandomInt.length - 1)];
  
  window.localStorage.setItem(STORAGE_KEY, String(Date.now()));
  
  randomBlockItem.classList.add('show');
} else {
  limitationBlock.classList.add('show');
}

не работает

voraa 01.02.2024 13:25

ruslan_mart,
Вот это не понятно, что означает (стр 14)
const randomBlockItem = blockList[getRandomInt(0, getRandomInt.length - 1)];

voraa 01.02.2024 13:28

Цитата:

Сообщение от Сергей Ракипов
люди ) помогите если сможете )

А что конкретно не работает?
Ну там нет никакого учета времени.

По коду, я не могу понять, что означают классы 'fact_picture_mini_curr', что означает префикс 'mini_' у id?
Как вообще верстка сделана? Какие классы у показываемых блоков, какие у них id? Какие классы у финального блока?

Сергей Ракипов 01.02.2024 13:45

Цитата:

Сообщение от voraa (Сообщение 554663)
А что конкретно не работает?
Ну там нет никакого учета времени.

Да просто не работает, даже ошибки нет

Вот код кусками весь не влазит

<main>
	<header>
		<div class="limitation">
			Достигнуто суточное ограничение
		</div>
	</header>
	<section class="block">

		<div class="fact_block" id="fact_0000">
			<div class="fact_title">
				<p>1 факт</p>
				<p>Лобовое стекло кабины Boeing 747-400</p>
			</div>
			<div class="fact_content">
				Одно лобовое стекло или оконная рама кабины Boeing 747-400 стоят столько же, сколько автомобиль BMW
			</div>
			<div class="fact_picture">
				<img src="picture/plane_0.jpg" alt="">
			</div>
			<div class="fact_source">
				<a href="https://novate.ru/blogs/180316/35535/" target="_parent">Источник</a>
			</div>
		</div>

		<div class="fact_block" id="fact_0001">
			<div class="fact_title">
				<p>2 факт</p>
				<p>Инверсионный след</p>
			</div>
			<div class="fact_content">
				Инверсионный след, который самолеты оставляют позади себя, состоит из водяного пара. Тонкий след говорит о том, что сейчас низкая влажность воздуха и ясная погода. А толстый, более длинный след может являться ранним признаком шторма.
			</div>
			<div class="fact_picture">
				<img src="picture/plane_1.jpg" alt="">
			</div>
			<div class="fact_source">
				<a href="https://novate.ru/blogs/180316/35535/" target="_parent">Источник</a>
			</div>
		</div>

		<div class="fact_block" id="fact_0002">
			<div class="fact_title">
				<p>3 факт</p>
				<p>Сброс топлива</p>
			</div>
			<div class="fact_content">
				Если самолет должен совершить аварийную посадку, то пилот может принять решение сбросить топливо из баков в крыльях. Хотя это случается не очень часто, подобное делается для того, чтобы уменьшить вес самолета. Топливо обычно испаряется, прежде чем достигнет земли.
			</div>
			<div class="fact_picture">
				<img src="picture/plane_2.jpg" alt="">
			</div>
			<div class="fact_source">
				<a href="https://novate.ru/blogs/180316/35535/" target="_parent">Источник</a>
			</div>
		</div>

		<div class="fact_block" id="fact_0003">
			<div class="fact_title">
				<p>4 факт</p>
				<p>Airbus A380</p>
			</div>
			<div class="fact_content">
				Самый большой в мире пассажирский самолет - Airbus A380. Этот двухэтажный реактивный лайнер с четырьмя двигателями совершил свой первый полет 27 апреля 2005 года.
			</div>
			<div class="fact_picture">
				<img src="picture/plane_3.jpg" alt="">
			</div>
			<div class="fact_source">
				<a href="https://novate.ru/blogs/180316/35535/" target="_parent">Источник</a>
			</div>
		</div>

		<div class="fact_block" id="fact_0004">
			<div class="fact_title">
				<p>5 факт</p>
				<p>BD-5 Micro</p>
			</div>
			<div class="fact_content">
				Самый маленький в мире реактивный самолет - BD-5 Micro. Его размах крыльев составляет от 4 до 6,5 метров, а весит самолет всего 160 кг
			</div>
			<div class="fact_picture">
				<img src="picture/plane_4.jpg" alt="">
			</div>
			<div class="fact_source">
				<a href="https://novate.ru/blogs/180316/35535/" target="_parent">Источник</a>
			</div>
		</div>

		<div class="fact_block" id="full_collection">
			<div class="fact_title">
				<p>Полная коллекция</p>
			</div>
			<div class="fact_content">
				Коллекция фактов собрана
			</div>
			<div class="fact_picture">
				<img src="picture/plane_5.jpg" alt="">
			</div>
			<div class="fact_source">
				<a href="https://novate.ru/blogs/180316/35535/" target="_parent">Источник</a>
			</div>
		</div>

	</section>

	<section class="current">

		<div class="fact_block" id="curr_0000">
			<div class="fact_title">
				<p>1 факт</p>
				<p>Лобовое стекло кабины Boeing 747-400</p>
			</div>
			<div class="fact_content">
				Одно лобовое стекло или оконная рама кабины Boeing 747-400 стоят столько же, сколько автомобиль BMW
			</div>
			<div class="fact_picture">
				<img src="picture/plane_0.jpg" alt="">
			</div>
			<div class="fact_source">
				<a href="https://novate.ru/blogs/180316/35535/" target="_parent">Источник</a>
			</div>
		</div>

		<div class="fact_block" id="curr_0001">
			<div class="fact_title">
				<p>2 факт</p>
				<p>Инверсионный след</p>
			</div>
			<div class="fact_content">
				Инверсионный след, который самолеты оставляют позади себя, состоит из водяного пара. Тонкий след говорит о том, что сейчас низкая влажность воздуха и ясная погода. А толстый, более длинный след может являться ранним признаком шторма.
			</div>
			<div class="fact_picture">
				<img src="picture/plane_1.jpg" alt="">
			</div>
			<div class="fact_source">
				<a href="https://novate.ru/blogs/180316/35535/" target="_parent">Источник</a>
			</div>
		</div>

		<div class="fact_block" id="curr_0002">
			<div class="fact_title">
				<p>3 факт</p>
				<p>Сброс топлива</p>
			</div>
			<div class="fact_content">
				Если самолет должен совершить аварийную посадку, то пилот может принять решение сбросить топливо из баков в крыльях. Хотя это случается не очень часто, подобное делается для того, чтобы уменьшить вес самолета. Топливо обычно испаряется, прежде чем достигнет земли.
			</div>
			<div class="fact_picture">
				<img src="picture/plane_2.jpg" alt="">
			</div>
			<div class="fact_source">
				<a href="https://novate.ru/blogs/180316/35535/" target="_parent">Источник</a>
			</div>
		</div>

		<div class="fact_block" id="curr_0003">
			<div class="fact_title">
				<p>4 факт</p>
				<p>Airbus A380</p>
			</div>
			<div class="fact_content">
				Самый большой в мире пассажирский самолет - Airbus A380. Этот двухэтажный реактивный лайнер с четырьмя двигателями совершил свой первый полет 27 апреля 2005 года.
			</div>
			<div class="fact_picture">
				<img src="picture/plane_3.jpg" alt="">
			</div>
			<div class="fact_source">
				<a href="https://novate.ru/blogs/180316/35535/" target="_parent">Источник</a>
			</div>
		</div>

		<div class="fact_block" id="curr_0004">
			<div class="fact_title">
				<p>5 факт</p>
				<p>BD-5 Micro</p>
			</div>
			<div class="fact_content">
				Самый маленький в мире реактивный самолет - BD-5 Micro. Его размах крыльев составляет от 4 до 6,5 метров, а весит самолет всего 160 кг
			</div>
			<div class="fact_picture">
				<img src="picture/plane_4.jpg" alt="">
			</div>
			<div class="fact_source">
				<a href="https://novate.ru/blogs/180316/35535/" target="_parent">Источник</a>
			</div>
		</div>

	</section>

	<section class="mini">

		<div class="fact_picture_mini" id="mini_0000" >
			<img src="picture/plane_0.jpg" width="100%" alt="">
		</div>
		<div class="fact_picture_mini" id="mini_0001">
			<img src="picture/plane_1.jpg" width="100%" alt="">
		</div>
		<div class="fact_picture_mini" id="mini_0002">
			<img src="picture/plane_2.jpg" width="100%" alt="">
		</div>
		<div class="fact_picture_mini" id="mini_0003">
			<img src="picture/plane_3.jpg" width="100%" alt="">
		</div>
		<div class="fact_picture_mini" id="mini_0004">
			<img src="picture/plane_4.jpg" width="100%" alt="">
		</div>

	</section>
	<footer></footer>
</main>

Сергей Ракипов 01.02.2024 13:46

main{
  width: 100%;
}
header{
  height: 60px;
  margin: 0px auto 0px;
  max-width: 640px;
  min-width: 320px;
}

footer{
  height: 60px;
}

section{
  margin: 0px auto 0px;
  max-width: 640px;
  min-width: 320px;
  position: static;
}
section.block{
  margin: 0px auto 0px;
  max-width: 640px;
  min-width: 320px;
  position: relative;
}

.fact_block {
  display: none;
  position: relative;
  margin: 20px 0px 20px 0px;
  padding: 0px 20px 0px 20px;
}
.fact_title {
  margin: 20px 0px 20px 0px;
  height: 60px;
}
.fact_content {
  margin: 20px 0px 20px 0px;
  height: 180px;
  height: auto;
}
.fact_source {
  margin: 20px 0px 20px 0px;
}
.fact_source > a {

}
.fact_picture {
  margin: 20px 0px 20px 0px;
}
.fact_picture > img {
  width: 100%;
}
.show{
  display: block;
}
.limitation{
  text-align: center;
  padding: 40px 0px 0px 0px;
  display: none;
}
.mini{
  display: flex;
  justify-content: center;
  align-items: center;
}
.fact_picture_mini{
  width: 80px;
  padding: 0px 10px 0px 10px;
  filter: grayscale(100%);
  pointer-events: none;
}

.fact_picture_mini_curr{
  filter: grayscale(0%);
  cursor: pointer;
  pointer-events: auto;
}

ruslan_mart 01.02.2024 14:25

Сорян, торопился и опечатался. Работает:

function getRandomInt(min, max) {
  return Math.floor(Math.random() * (max - min) + min);
}

const blockList = Array.from(document.querySelectorAll('.fact_block'));
const limitationBlock = document.querySelector('.limitation');

const INTERVAL = 1000 * 60 *  60 * 10; // 10 часов
const STORAGE_KEY = 'random-block';

const currentStorageValue = Number(window.localStorage.getItem(STORAGE_KEY));

if (blockList.length > 0 && ((Number.isNaN(currentStorageValue) || currentStorageValue < Date.now() - INTERVAL))) {
  const randomBlockItem = blockList[getRandomInt(0, blockList.length - 1)];
  
  window.localStorage.setItem(STORAGE_KEY, String(Date.now()));
  
  randomBlockItem.classList.add('show');
} else {
  limitationBlock.classList.add('show');
}


<div>
  <div class="fact_block">1</div>
  <div class="fact_block">2</div>
  <div class="fact_block">3</div>
  <div class="fact_block">4</div>
  <div class="fact_block">5</div>
</div>

<div class="limitation">limitation</div>


.fact_block, .limitation {
  display: none;
}

.fact_block.show, .limitation.show {
  display: block;
}

voraa 01.02.2024 15:05

Ну вот такой работающий вариант. Просто, как пример. Ваш код слишком большой для изучения
(Интервал установлен в 15 сек
<!DOCTYPE html>
<html lang="ru">
	<head>
		<title>Блоки</title>
		<style>
			.fact_block {
				position: relative;
				width: 300px;
				height: 200px;
				border: 1px solid blue;
				display: none;
			}
			.final_block {
				border: 1px solid red;
			}
            .show {
                display: block;
            }
		</style>
	</head>
	<body>
		<div id="f1" class="fact_block">Block 1</div>
		<div id="f2" class="fact_block">Block 2</div>
		<div id="f3" class="fact_block">Block 3</div>
		<div id="f4" class="fact_block">Block 4</div>
		<div id="f5" class="fact_block">Block 5</div>
		<div id="f6" class="fact_block">Block 6</div>
		<div id="f7" class="fact_block">Block 7</div>
		<div id="f8" class="fact_block">Block 8</div>
		<div id="f9" class="fact_block">Block 9</div>
		<div id="final" class="fact_block final_block">Final Block</div>

		<script>
			function showRandomBlock() {
				const INTERVAL = 15 * 1000; // 15s; 10 * 60 * 60 * 1000 = 10h
				const KEY_SHOWNBLOCKS = 'key-shown-blocks';
				const KEY_LASTTIMESHOW = 'last-tyme-show';

				const getShownBlocks = () => {
					let s = window.localStorage.getItem(KEY_SHOWNBLOCKS);
					return s ? JSON.parse(s) : [];
				};

				const addShownBlocks = (idblock) => {
					const blocks = getShownBlocks();
					blocks.push(idblock);
					window.localStorage.setItem(
						KEY_SHOWNBLOCKS,
						JSON.stringify(blocks)
					);
				};

				const getLastTime = () => {
					let s = window.localStorage.getItem(KEY_LASTTIMESHOW);
					return s ? Number(s) : 0;
				};

				const setLastTime = () => {
					const time = Date.now();
					window.localStorage.setItem(KEY_LASTTIMESHOW, time);
				};

				const showBlock = (id) => {
					document.getElementById(id).classList.add('show');
				};

				const showLastBlock = () => {
					const shownBlocks = getShownBlocks();
					const id = shownBlocks.at(-1);
					showBlock(id);
				};

				const getRandomInt = (min, max) => {
					return Math.floor(Math.random() * (max - min) + min);
				};

				const showNewBlock = () => {
					const factBlocks = [
						...document.querySelectorAll(
							'.fact_block:not(.final_block)'
						),
					].map((block) => block.id);
					const shownBlocks = getShownBlocks();

					const availableBlocks = factBlocks.filter(
						(id) => !shownBlocks.includes(id)
					);
                    if (availableBlocks.length === 0) {
                        const idlast = document.querySelector('.final_block').id
                        showBlock(idlast)
                    } else {
                        const index = getRandomInt(0, availableBlocks.length);
                        const idblock = availableBlocks[index];
                        showBlock(idblock);
                        addShownBlocks(idblock);
                        setLastTime();
                    }
				};

				const lastTime = getLastTime();
				if (lastTime + INTERVAL < Date.now()) {
					showNewBlock();
				} else {
					showLastBlock();
				}
			}

			showRandomBlock();
		</script>
	</body>
</html>


Блоки, которые могут показываться должны иметь класс 'fact_block'. Заключительный блок, кроме этого должен иметь класс 'final_block'. Для показа блока, ему добавляется класс 'show'

voraa 01.02.2024 15:32

Я видно не так понял эту задачу.
Я показываю, какой то блок в течении все заданного интервала. Интервал закончился, начался новый я показываю другой блок. Когда все блоки закончатся показываю все время последний.

Сейчас переделаю


Часовой пояс GMT +3, время: 23:02.