# Лабораторна робота №3
## 1. Постановка Задачі
Протестувати та продемонструвати результати оцінки випадкових величин для браузерної сторони додатку, що запускається:
а) на комп’ютері, пов’язаному провідним зв’язком з мережею інтернет;
б) на комп’ютері, пов’язаному WiFi-зв’язком з мережею інтернет;
в) на мобільному пристрої, пов’язаному з мережею інтернет через мобільні (стільникові) канали;
Самостійно вибрати передбачуваний Вами закон розподілу випадкової величини з набору:
**б) Розподіл Пуассона**
Для обраного розподілу за даними роботи клієнт-серверної програми отримати оцінки випадкової величини :
- min - мінімум
- перший (або нижній) квартiль
- med - медіана або другий квартiль
- avg - середнє арифметичне
- mode - мода
- третій (або верхній) квартiль
- max - максимум
- stddev - стандартне відхилення
- інтерквартiльний розмах
**Варіант 1**. Спрощена синхронізація годинника клієнта та годинника сервера
Створити на хостингу replit.com клієнт-серверний додаток, що, використовуючи протокол HTTP, виконує синхронізацію годинника клієнта та годинника сервера (обчислення поправки) та online порівняння її з роботою бібліотеки tymesync, приймаючи гіпотезу симетричності каналу. Дайте оцінку похибки методу визначення початкової синхрокорекції.
## 2. Теоретичні відомості
- **Розподіл Пуассона**: Це дискретний розподіл, який використовується для моделювання кількості подій, які сталися за фіксований час або в фіксованому просторі, якщо події відбуваються незалежно з фіксованою імовірністю в кожному інтервалі.
- Характеристики випадкової величини:
1. **Мінімум (min)** - найменше значення вибірки.
2. **Перший квартиль (Q1)** - значення, яке розділяє перші 25% вибірки.
3. **Медіана (med)** - значення, яке розділяє першу половину вибірки від другої.
4. **Середнє арифметичне (avg)** - сума всіх значень поділено на кількість значень.
5. **Мода (mode)** - значення з найбільшою частотою вибірки.
6. **Третій квартиль (Q3)** - значення, яке розділяє перші 75% вибірки.
7. **Максимум (max)** - найбільше значення вибірки.
8. **Стандартне відхилення (stddev)** - міра розсіювання значень від середнього.
9. **Інтерквартільний розмах (IQR)** - різниця між третім та першим квартилями.
## 3. Результати
### 3.1 Таблиця результатів
| Тип каналу та величини | min | $q_{1/4}$ | med | avg | mode | $q_{3/4}$ | max | stddev | $I_q$ |
|------------------------|-----|------|-----|--------|------|------|-----|--------|----|
| wired $\theta$ | 184 | 186 | 188 | 190,96 | 187 | 191 | 304 | 12,95 | 5 |
| wifi $\theta$ | 184 | 189 | 190 | 200,5 | 189 | 193 | 473 | 39,54 | 4 |
| mobile $\theta$ | 214 | 225 | 232 | 233,7 | 240 | 241 | 259 | 10,82 | 16 |
| wired $\varepsilon_a$ | 184 | 187 | 189 | 194,98 | 186 | 195 | 335 | 18,91 | 8 |
| wifi $\varepsilon_a$ | 186 | 188 | 190 | 191,39 | 188 | 194 | 206 | 4,35 | 6 |
| mobile $\varepsilon_a$ | 212 | 220 | 229 | 233,26 | 217 | 238 | 380 | 22,19 | 18 |
### 3.2 На комп’ютері, пов’язаному провідним зв’язком з мережею інтернет

### 3.3 На комп’ютері, пов’язаному WiFi-зв’язком з мережею інтернет;

### 3.4 На мобільному пристрої, пов’язаному з мережею інтернет через мобільні (стільникові) канали.

## 4. Інтерпретація результатів
Для всіх типів з'єднань різниця невелика що для власне розробленої функції, що для бібліотеки timesync оскільки там різниця в методі оцінки затримки є невеликою і помітити суттєву різницю в їх роботі є проблематичним. Це свідчить про те, що розроблена програма в цілому працює правильно і видає значення практично ідентичні з бібліотекою. Якби ми використовували не віддалений сервер, а локальний клієнт, роботу цих двох методів можна було б більш точно оцінити.
## 5 Висновок
В цій роботі було проведено оцінку випадкових величин для браузерної сторони додатку, що запускається на різних пристроях із з'єднанням з мережею Інтернет. В якості передбачуваного закону розподілу випадкової величини було обрано Розподіл Пуассона.
Для обраного розподілу були отримані оцінки різних статистик, таких як мінімум, перший квартиль, медіана, середнє арифметичне, мода, третій квартиль, максимум, стандартне відхилення і інтерквартильний розмах. Ці оцінки допомогли зрозуміти розподіл даних та їх характеристики.
У варіанті 1 також була розглянута синхронізація годинників клієнта та сервера у клієнт-серверному додатку через протокол HTTP. Для цього було використано хостинг replit.com та порівняно метод синхронізації з роботою бібліотеки tymesync. Оцінка похибки методу визначення початкової синхрокорекції дозволяє зрозуміти ефективність та точність цього процесу.
## Додаток
Посилання на replit - https://replit.com/@nikitafilipenko/lab3
index.js файл
```javascript
const express = require("express");
const timesyncServer = require("timesync/server");
// create an express app
var port = 8081;
var app = express();
app.listen(port);
console.log("Server listening:" + port);
// serve static index.html -------------------------
app.get("/", express.static(__dirname));
app.use(express.static(__dirname));
// handle timesync requests -------------------------
app.use("/timesync", timesyncServer.requestHandler);
// Роутер для GET-запроса
app.get("/randomStats", (req, res) => {
// Логика обработки GET-запроса
res.send("Hello, world!");
});
```
rtt.js файл
```javascript
let rttAuto = 0;
// Функция для отправки GET-запроса и измерения RTT
async function sendGetRequest(url) {
const startTime = Date.now();
await fetch(url); // Отправляем GET-запрос
const endTime = Date.now();
const rtt = endTime - startTime;
return rtt;
}
async function sendGetRequestTimeSync(url) {
const ts = timesync.create({
server: "/timesync", // URL сервера для синхронизации времени
interval: 1000 * 60 * 15, // Интервал синхронизации (15 минут)
});
var now = new Date(ts.now());
await fetch(url);
const endTime = Date.now();
const rtt = endTime - now;
return rtt;
}
// Основная функция
async function main() {
const url = "/randomStats";
const rttArray = [];
const timesyncArray = [];
// Отправляем 100 запросов
for (let i = 0; i < 100; i++) {
const rtt = await sendGetRequest(url);
rttArray.push(rtt);
console.log(`Request ${i + 1}: RTT = ${rtt} ms`);
}
for (let i = 0; i < 100; i++) {
const autoRtt = await sendGetRequestTimeSync(url);
timesyncArray.push(autoRtt);
console.log(`Request ${i + 1}: Offset = ${autoRtt} ms`);
}
analyse(rttArray, timesyncArray);
}
//Функция для подсчета результатов
function analyse(rtt, timesync) {
let data_min = rtt.map(function (value) {
return value - Math.min(...rtt);
});
let data_min_timesync = timesync.map(function (value) {
return value - Math.min(...timesync);
});
//Минимум
let min = Math.min(...rtt);
let mintimesync = Math.min(...timesync);
//Максимум
let max = Math.max(...rtt);
let maxtimesync = Math.max(...timesync);
//Среднее
let mean =
rtt.reduce((accumulator, currentValue) => accumulator + currentValue, 0) /
rtt.length;
let meantimesync =
timesync.reduce(
(accumulator, currentValue) => accumulator + currentValue,
0,
) / timesync.length;
//Подготавливаю данные к анализу квартилей
const sortedData = rtt.sort((a, b) => a - b); // Сортируем данные
const N = sortedData.length; // Получаем размерность
const sortedDataTimeSync = timesync.sort((a, b) => a - b); // Сортируем данные
const M = sortedDataTimeSync.length; // Получаем размерность
// Рассчет позиций квартилей
const q1Position = Math.floor((N + 1) / 4);
const q2Position = Math.floor(N / 2);
const q3Position = Math.floor((3 * (N + 1)) / 4);
// Рассчет позиций квартилей
const q1PositionTimeSync = Math.floor((M + 1) / 4);
const q2PositionTimeSync = Math.floor(M / 2);
const q3PositionTimeSync = Math.floor((3 * (M + 1)) / 4);
// Рассчет медианы
let medianValue;
if (N % 2 === 0) {
medianValue = (sortedData[q2Position - 1] + sortedData[q2Position]) / 2;
} else {
medianValue = sortedData[q2Position];
}
let medianValueTimeSync;
if (N % 2 === 0) {
medianValueTimeSync =
(sortedDataTimeSync[q2PositionTimeSync - 1] +
sortedDataTimeSync[q2PositionTimeSync]) /
2;
} else {
medianValueTimeSync = sortedDataTimeSync[q2PositionTimeSync];
}
// Рассчет первого квартиля
let q1Value;
if (q1Position === q1Position) {
q1Value = sortedData[q1Position - 1];
} else {
q1Value = (sortedData[q1Position - 1] + sortedData[q1Position]) / 2;
}
let q1ValueTimeSync;
if (q1PositionTimeSync === q1PositionTimeSync) {
q1ValueTimeSync = sortedDataTimeSync[q1PositionTimeSync - 1];
} else {
q1ValueTimeSync =
(sortedDataTimeSync[q1PositionTimeSync - 1] +
sortedDataTimeSync[q1PositionTimeSync]) /
2;
}
// Рассчет третьего квартиля
let q3Value;
if (q3Position === q3Position) {
q3Value = sortedData[q3Position - 1];
} else {
q3Value = (sortedData[q3Position - 1] + sortedData[q3Position]) / 2;
}
let q3ValueTimeSync;
if (q3PositionTimeSync === q3PositionTimeSync) {
q3ValueTimeSync = sortedDataTimeSync[q3PositionTimeSync - 1];
} else {
q3ValueTimeSync =
(sortedDataTimeSync[q3PositionTimeSync - 1] +
sortedDataTimeSync[q3PositionTimeSync]) /
2;
}
const frequencyTable = {};
for (let value of sortedData) {
if (value in frequencyTable) {
frequencyTable[value]++;
} else {
frequencyTable[value] = 1;
}
}
const frequencyTableTimeSync = {};
for (let valueTimeSync of sortedDataTimeSync) {
if (valueTimeSync in frequencyTableTimeSync) {
frequencyTableTimeSync[valueTimeSync]++;
} else {
frequencyTableTimeSync[valueTimeSync] = 1;
}
}
//Мода
let mode = null;
let maxCount = 0;
for (const value in frequencyTable) {
const count = frequencyTable[value];
if (count > maxCount) {
maxCount = count;
mode = value;
}
}
let modeTimeSync = null;
let maxCountTimeSync = 0;
for (const valueTimeSync in frequencyTableTimeSync) {
const countTimeSync = frequencyTableTimeSync[valueTimeSync];
if (countTimeSync > maxCountTimeSync) {
maxCountTimeSync = countTimeSync;
modeTimeSync = valueTimeSync;
}
}
// Рассчет отклонений
let squaredDeviations = [];
for (let value of sortedData) {
const deviation = value - mean;
squaredDeviations.push(deviation * deviation);
}
let squaredDeviationsTimeSync = [];
for (let value of sortedDataTimeSync) {
const deviation = value - meantimesync;
squaredDeviationsTimeSync.push(deviation * deviation);
}
// Рассчет дисперсии
let variance = 0;
for (let squaredDeviation of squaredDeviations) {
variance += squaredDeviation;
}
variance /= N;
let varianceTimeSync = 0;
for (let squaredDeviationTimeSync of squaredDeviationsTimeSync) {
varianceTimeSync += squaredDeviationTimeSync;
}
varianceTimeSync /= M;
// Среднее отклонение
const standardDeviation = Math.sqrt(variance);
const standardDeviationTimeSync = Math.sqrt(varianceTimeSync);
// Интерквантильный размах
const IQR = q3Value - q1Value;
const IQRTimeSync = q3ValueTimeSync - q1ValueTimeSync;
let info = document.getElementById("Info");
info.innerHTML =
"θ Минимум: " +
min +
"<br>" +
"θ Максимум: " +
max +
"<br>" +
"θ Медиана: " +
medianValue +
"<br>" +
"θ Мода: " +
mode +
"<br>" +
"θ Среднее значение: " +
mean +
"<br>" +
"θ Первый квартиль: " +
q1Value +
"<br>" +
"θ Третий квартиль: " +
q3Value +
"<br>" +
"θ Интерквантильный размах: " +
IQR +
"<br>" +
"θ Среднее квадратичное отклонение: " +
standardDeviation +
"<br>";
let timesyncInfo = document.getElementById("timesyncInfo");
timesyncInfo.innerHTML =
"<br>ξ Минимум: " +
mintimesync +
"<br>" +
"ξ Максимум: " +
maxtimesync +
"<br>" +
"ξ Медиана: " +
medianValueTimeSync +
"<br>" +
"ξ Мода: " +
modeTimeSync +
"<br>" +
"ξ Среднее значение: " +
meantimesync +
"<br>" +
"ξ Первый квартиль: " +
q1ValueTimeSync +
"<br>" +
"ξ Третий квартиль: " +
q3ValueTimeSync +
"<br>" +
"ξ Интерквантильный размах: " +
IQRTimeSync +
"<br>" +
"ξ Среднее квадратичное отклонение: " +
standardDeviationTimeSync;
}
// Вызываем основную функцию
main();
```