add all practicals

This commit is contained in:
2025-12-23 18:51:04 +02:00
commit 1b089f2f67
56 changed files with 38985 additions and 0 deletions

1
code Submodule

Submodule code added at fe3dc015f2

1
code_java Symbolic link
View File

@@ -0,0 +1 @@
/home/dxrkness/Downloads/git-projects/itroi/

17
doc.yaml Normal file
View File

@@ -0,0 +1,17 @@
subject: ІТРОІ
doctype: ПЗ
mentors:
- name: Мірошниченко Н.С.
degree: Асистент кафедри СТ
gender: f
edu_program: &EDU КНТ
university: ХНУРЕ
authors:
- name: Орлов О. С.
# full_name_gen: Косач Лариси Петрівни
course: 4
edu: *EDU
gender: m
group: 22-1
semester: 7
# variant:

0
nohup.out Normal file
View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

BIN
pz1/all-validate.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

BIN
pz1/all_files.zip Normal file

Binary file not shown.

15
pz1/bibl.yml Normal file
View File

@@ -0,0 +1,15 @@
libxml2:
type: Web
title: libxml2
author:
url:
value: https://gitlab.gnome.org/GNOME/libxml2
date: 2025-11-08
ajv:
type: Web
title: avj
author:
url:
value: https://ajv.js.org/
date: 2025-11-08

1
pz1/doc.yaml Symbolic link
View File

@@ -0,0 +1 @@
../doc.yaml

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 KiB

70
pz1/freight-schema.json Normal file
View File

@@ -0,0 +1,70 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://nure.ua/itroi/freight-schema.json",
"title": "Freight management schema",
"description": "Describes domain objects of freights",
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "integer",
"minimum": 1
},
"name": {
"type": "string",
"minLength": 3,
"maxLength": 128
},
"description": {
"type": "string",
"maxLength": 500
},
"weight_kg": {
"type": "number",
"exclusiveMinimum": 0,
"exclusiveMaximum": 4294967296
},
"dimensions": {
"type": "object",
"properties": {
"width_cm": {
"type": "number",
"minimum": 1,
"maximum": 150000
},
"height_cm": {
"type": "number",
"minimum": 1,
"maximum": 150000
},
"length_cm": {
"type": "number",
"minimum": 1,
"maximum": 150000
}
},
"required": [
"width_cm",
"height_cm",
"length_cm"
]
},
"status": {
"type": "string",
"enum": [
"PENDING",
"IN_TRANSIT",
"DELIVERED"
]
}
},
"required": [
"id",
"name",
"weight_kg",
"dimensions",
"status"
]
}
}

89
pz1/freight-schema.xsd Normal file
View File

@@ -0,0 +1,89 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="https://nure.ua/itroi/freight-schema"
xmlns:tns="https://nure.ua/itroi/freight-schema"
elementFormDefault="qualified">
<xs:element name="freights" type="tns:FreightArray"/>
<xs:complexType name="FreightArray">
<xs:sequence>
<xs:element name="freight" type="tns:Freight" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="Freight">
<xs:all>
<xs:element name="id">
<xs:simpleType>
<xs:restriction base="xs:integer">
<xs:minInclusive value="1"/>
<xs:maxExclusive value="4294967296"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="name">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:minLength value="3"/>
<xs:maxLength value="128"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="description" minOccurs="0">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:maxLength value="500"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="weight_kg">
<xs:simpleType>
<xs:restriction base="xs:decimal">
<xs:minExclusive value="0"/>
<xs:maxExclusive value="4294967296"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="dimensions" type="tns:Dimensions"/>
<xs:element name="status">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="PENDING"/>
<xs:enumeration value="IN_TRANSIT"/>
<xs:enumeration value="DELIVERED"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:all>
</xs:complexType>
<xs:complexType name="Dimensions">
<xs:all>
<xs:element name="width_cm">
<xs:simpleType>
<xs:restriction base="xs:decimal">
<xs:minInclusive value="1"/>
<xs:maxInclusive value="150000"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="height_cm">
<xs:simpleType>
<xs:restriction base="xs:decimal">
<xs:minInclusive value="1"/>
<xs:maxInclusive value="150000"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="length_cm">
<xs:simpleType>
<xs:restriction base="xs:decimal">
<xs:minInclusive value="1"/>
<xs:maxInclusive value="150000"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:all>
</xs:complexType>
</xs:schema>

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 KiB

37
pz1/freights.json Normal file
View File

@@ -0,0 +1,37 @@
[
{
"id": 1,
"name": "Electronics Shipment",
"description": "A mixed pallet of consumer electronics.",
"weight_kg": 750.5,
"dimensions": {
"width_cm": 120,
"height_cm": 100,
"length_cm": 120
},
"status": "PENDING"
},
{
"id": 2,
"name": "Fresh Produce",
"description": "Temperature-controlled container of fresh fruits and vegetables.",
"weight_kg": 1200,
"dimensions": {
"width_cm": 240,
"height_cm": 250,
"length_cm": 600
},
"status": "IN_TRANSIT"
},
{
"id": 3,
"name": "Automotive Parts",
"weight_kg": 3500,
"dimensions": {
"width_cm": 200,
"height_cm": 180,
"length_cm": 300
},
"status": "DELIVERED"
}
]

41
pz1/freights.xml Normal file
View File

@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="freights.xsl"?>
<freights xmlns="https://nure.ua/itroi/freight-schema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://nure.ua/itroi/freight-schema freight-schema.xsd">
<freight>
<id>1</id>
<name>Electronics Shipment</name>
<description>A mixed pallet of consumer electronics.</description>
<weight_kg>750.5</weight_kg>
<dimensions>
<width_cm>120</width_cm>
<height_cm>100</height_cm>
<length_cm>120</length_cm>
</dimensions>
<status>PENDING</status>
</freight>
<freight>
<id>2</id>
<name>Fresh Produce</name>
<description>Temperature-controlled container of fresh fruits and vegetables.</description>
<weight_kg>1200</weight_kg>
<dimensions>
<width_cm>240</width_cm>
<height_cm>250</height_cm>
<length_cm>600</length_cm>
</dimensions>
<status>IN_TRANSIT</status>
</freight>
<freight>
<id>3</id>
<name>Automotive Parts</name>
<weight_kg>3500</weight_kg>
<dimensions>
<width_cm>200</width_cm>
<height_cm>180</height_cm>
<length_cm>300</length_cm>
</dimensions>
<status>DELIVERED</status>
</freight>
</freights>

73
pz1/freights.xsl Normal file
View File

@@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fs="https://nure.ua/itroi/freight-schema">
<xsl:output method="html" indent="yes" encoding="UTF-8"/>
<xsl:template match="/">
<html>
<head>
<title>Звіт по вантажах</title>
<link rel="stylesheet" type="text/css" href="index.css"/>
<script>
function filterFreights() {
var selectedStatus = document.getElementById('statusFilter').value;
var rows = document.querySelectorAll('#freightTable tbody tr');
rows.forEach(function(row) {
var status = row.getAttribute('data-status');
if (selectedStatus === 'ALL' || status === selectedStatus) {
row.classList.remove('hidden');
} else {
row.classList.add('hidden');
}
});
}
</script>
</head>
<body>
<h1>Інформація про вантажі</h1>
<div class="filter-container">
<label for="statusFilter">Фільтрувати за статусом:</label>
<select id="statusFilter" onchange="filterFreights()">
<option value="ALL">Всі статуси</option>
<option value="PENDING">PENDING</option>
<option value="IN_TRANSIT">IN_TRANSIT</option>
<option value="DELIVERED">DELIVERED</option>
</select>
</div>
<table id="freightTable">
<thead>
<tr>
<th>ID</th>
<th>Назва</th>
<th>Опис</th>
<th>Вага (кг)</th>
<th>Розміри (см)</th>
<th>Статус</th>
</tr>
</thead>
<tbody>
<xsl:apply-templates select="fs:freights/fs:freight"/>
</tbody>
</table>
</body>
</html>
</xsl:template>
<xsl:template match="fs:freight">
<tr data-status="{fs:status}">
<td><xsl:value-of select="fs:id"/></td>
<td><xsl:value-of select="fs:name"/></td>
<td><xsl:value-of select="fs:description"/></td>
<td><xsl:value-of select="fs:weight_kg"/></td>
<td>
<xsl:value-of select="fs:dimensions/fs:width_cm"/> x
<xsl:value-of select="fs:dimensions/fs:height_cm"/> x
<xsl:value-of select="fs:dimensions/fs:length_cm"/>
</td>
<td><xsl:value-of select="fs:status"/></td>
</tr>
</xsl:template>
</xsl:stylesheet>

67
pz1/index.css Normal file
View File

@@ -0,0 +1,67 @@
body {
font-family: Arial, sans-serif;
margin: 20px;
background-color: #f4f4f9;
color: #333;
}
h1 {
font-size: 2em;
color: #1d3557;
border-bottom: 3px solid #457b9d;
padding-bottom: 10px;
text-align: center;
}
.filter-container {
display: flex;
justify-content: center;
align-items: center;
gap: 10px;
margin: 20px 0;
padding: 15px;
background-color: #fff;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.filter-container label {
font-weight: bold;
font-size: 1.1em;
color: #1d3557;
}
.filter-container select {
padding: 8px 12px;
border: 1px solid #a8dadc;
border-radius: 4px;
font-size: 1em;
min-width: 200px;
}
table {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
}
th, td {
border: 1px solid #a8dadc;
padding: 12px;
text-align: left;
}
th {
background-color: #457b9d;
color: white;
font-weight: bold;
}
tr:nth-child(even) {
background-color: #f1faee;
}
.hidden {
display: none;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

58
pz1/route-schema.json Normal file
View File

@@ -0,0 +1,58 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://nure.ua/itroi/route-schema.json",
"title": "Routes management schema",
"description": "Describes domain objects of routes",
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "integer",
"minimum": 1
},
"vehicle_id": {
"type": "integer"
},
"freight_id": {
"type": "array",
"items": {
"type": "integer"
},
"minItems": 1
},
"start_location": {
"type": "string"
},
"end_location": {
"type": "string"
},
"distance_km": {
"type": "number",
"minimum": 0
},
"estimated_duration_hours": {
"type": "number",
"minimum": 0
},
"status": {
"type": "string",
"enum": [
"PLANNED",
"IN_PROGRESS",
"COMPLETED",
"CANCELLED"
]
}
},
"required": [
"id",
"vehicle_id",
"freight_id",
"start_location",
"end_location",
"distance_km",
"status"
]
}
}

61
pz1/route-schema.xsd Normal file
View File

@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="https://nure.ua/itroi/route-schema"
xmlns:tns="https://nure.ua/itroi/route-schema"
elementFormDefault="qualified">
<xs:element name="routes" type="tns:RouteArray"/>
<xs:complexType name="RouteArray">
<xs:sequence>
<xs:element name="route" type="tns:Route" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="Route">
<xs:all>
<xs:element name="id">
<xs:simpleType>
<xs:restriction base="xs:integer">
<xs:minInclusive value="1"/>
<xs:maxExclusive value="4294967296"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="vehicle_id" type="xs:integer"/>
<xs:element name="freight_id">
<xs:complexType>
<xs:sequence>
<xs:element name="item" type="xs:integer" minOccurs="1" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="start_location" type="xs:string"/>
<xs:element name="end_location" type="xs:string"/>
<xs:element name="distance_km">
<xs:simpleType>
<xs:restriction base="xs:decimal">
<xs:minInclusive value="0"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="estimated_duration_hours" minOccurs="0">
<xs:simpleType>
<xs:restriction base="xs:decimal">
<xs:minInclusive value="0"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="status">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="PLANNED"/>
<xs:enumeration value="IN_PROGRESS"/>
<xs:enumeration value="COMPLETED"/>
<xs:enumeration value="CANCELLED"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:all>
</xs:complexType>
</xs:schema>

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

BIN
pz1/routes-xslt.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

49
pz1/routes.json Normal file
View File

@@ -0,0 +1,49 @@
[
{
"id": 1,
"vehicle_id": 2,
"freight_id": [
1
],
"start_location": "Warehouse A, New York, NY",
"end_location": "Distribution Center, Boston, MA",
"distance_km": 350.5,
"estimated_duration_hours": 5.5,
"status": "PLANNED"
},
{
"id": 2,
"vehicle_id": 1,
"freight_id": [
2,
3
],
"start_location": "Port of Los Angeles, CA",
"end_location": "Las Vegas Warehouse, NV",
"distance_km": 450,
"estimated_duration_hours": 6,
"status": "IN_PROGRESS"
},
{
"id": 3,
"vehicle_id": 3,
"freight_id": [
2
],
"start_location": "Chicago Hub, IL",
"end_location": "St. Louis Depot, MO",
"distance_km": 480.2,
"status": "COMPLETED"
},
{
"id": 4,
"vehicle_id": 1,
"freight_id": [
3
],
"start_location": "Miami Port, FL",
"end_location": "Orlando Distribution, FL",
"distance_km": 380,
"status": "CANCELLED"
}
]

53
pz1/routes.xml Normal file
View File

@@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="routes.xsl"?>
<routes xmlns="https://nure.ua/itroi/route-schema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://nure.ua/itroi/route-schema route-schema.xsd">
<route>
<id>1</id>
<vehicle_id>2</vehicle_id>
<freight_id>
<item>1</item>
</freight_id>
<start_location>Warehouse A, New York, NY</start_location>
<end_location>Distribution Center, Boston, MA</end_location>
<distance_km>350.5</distance_km>
<estimated_duration_hours>5.5</estimated_duration_hours>
<status>PLANNED</status>
</route>
<route>
<id>2</id>
<vehicle_id>1</vehicle_id>
<freight_id>
<item>2</item>
<item>3</item>
</freight_id>
<start_location>Port of Los Angeles, CA</start_location>
<end_location>Las Vegas Warehouse, NV</end_location>
<distance_km>450</distance_km>
<estimated_duration_hours>6</estimated_duration_hours>
<status>IN_PROGRESS</status>
</route>
<route>
<id>3</id>
<vehicle_id>3</vehicle_id>
<freight_id>
<item>2</item>
</freight_id>
<start_location>Chicago Hub, IL</start_location>
<end_location>St. Louis Depot, MO</end_location>
<distance_km>480.2</distance_km>
<status>COMPLETED</status>
</route>
<route>
<id>4</id>
<vehicle_id>1</vehicle_id>
<freight_id>
<item>3</item>
</freight_id>
<start_location>Miami Port, FL</start_location>
<end_location>Orlando Distribution, FL</end_location>
<distance_km>380</distance_km>
<status>CANCELLED</status>
</route>
</routes>

75
pz1/routes.xsl Normal file
View File

@@ -0,0 +1,75 @@
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:rs="https://nure.ua/itroi/route-schema">
<xsl:output method="html" indent="yes" encoding="UTF-8"/>
<xsl:template match="/">
<html>
<head>
<title>Інформація про маршрути</title>
<link rel="stylesheet" type="text/css" href="index.css"/>
<script>
function filterRoutes() {
var selectedStatus = document.getElementById('statusFilter').value;
var rows = document.querySelectorAll('#routeTable tbody tr');
rows.forEach(function(row) {
var status = row.getAttribute('data-status');
if (selectedStatus === 'ALL' || status === selectedStatus) {
row.classList.remove('hidden');
} else {
row.classList.add('hidden');
}
});
}
</script>
</head>
<body>
<h1>Деталі маршрутів</h1>
<div class="filter-container">
<label for="statusFilter">Фільтрувати за статусом:</label>
<select id="statusFilter" onchange="filterRoutes()">
<option value="ALL">Всі статуси</option>
<option value="PLANNED">PLANNED</option>
<option value="IN_PROGRESS">IN_PROGRESS</option>
<option value="COMPLETED">COMPLETED</option>
<option value="CANCELLED">CANCELLED</option>
</select>
</div>
<table id="routeTable">
<thead>
<tr>
<th>ID</th>
<th>ID Транспорту</th>
<th>ID Вантажів</th>
<th>Звідки</th>
<th>Куди</th>
<th>Статус</th>
</tr>
</thead>
<tbody>
<xsl:apply-templates select="rs:routes/rs:route"/>
</tbody>
</table>
</body>
</html>
</xsl:template>
<xsl:template match="rs:route">
<tr data-status="{rs:status}">
<td><xsl:value-of select="rs:id"/></td>
<td><xsl:value-of select="rs:vehicle_id"/></td>
<td>
<xsl:for-each select="rs:freight_id/rs:item">
<xsl:value-of select="."/>
<xsl:if test="position() != last()">, </xsl:if>
</xsl:for-each>
</td>
<td><xsl:value-of select="rs:start_location"/></td>
<td><xsl:value-of select="rs:end_location"/></td>
<td><xsl:value-of select="rs:status"/></td>
</tr>
</xsl:template>
</xsl:stylesheet>

740
pz1/schema.txt Normal file
View File

@@ -0,0 +1,740 @@
// Academic aliases {{{1
#let universities = yaml("config/universities.yaml")
// Template formatting functions {{{1
/// numberless heading
#let nheading(title) = heading(depth: 1, numbering: none, title)
/// fill horizontal space with a box and not an empty space
#let hfill(width) = box(
width: width,
repeat(""),
) // NOTE: This is a HAIR SPACE (U+200A), not a regular space
/// make underlined cell with filled value
#let uline(align: center, content) = underline[
#if align != left { hfill(1fr) }
#content
#if align != right { hfill(1fr) }
]
/// bold text
#let bold(content) = text(weight: "bold")[#content]
/// month name from its number
#let month_gen(month) = (
"січня",
"лютого",
"березня",
"квітня",
"травня",
"червня",
"липня",
"серпня",
"вересня",
"жовтня",
"листопада",
"грудня",
).at(month - 1)
// Helper functions {{{1
/// captioned image with label derived from path:
/// - "image.png" = @image
/// - "img/image.png" = @image
/// - "img/foo/image.png" = @foo_image
/// - "img/foo/foo_image.png" = @foo_image
/// the caption will be modified based on a conditional positional value:
/// - `none`: no change
/// - some value: "`caption` (за даними `value`)"
/// - no value: "`caption` (рисунок виконано само"стійно)"
/// additional named arguments will be passed to original `image` function
#let img(bytes, path, caption, ..sink) = {
let parts = path.split(".").first().split("/")
let label_string = if (
parts.len() <= 2 or parts.at(-1).starts-with(parts.at(-2))
) {
// ("image",), (_, "image") and (.., "img", "img_image")
parts.last()
} else {
// (.., "img", "image") = "img_image"
parts.at(-2) + "_" + parts.at(-1)
}.replace(" ", "_")
let caption = if sink.pos().len() == 0 {
caption
} else if sink.pos().first() == none {
caption + " (рисунок виконано самостійно)"
} else {
[#caption (за даними #sink.pos().first())]
}
[#figure(
// image(read(path, encoding: none)),
image(bytes, ..sink.named()),
caption: caption,
) #label(label_string)]
}
#let spacing = 0.95em // spacing between lines
#let num-to-alpha = "абвгдежиклмнпрстуфхцшщюя".split("") // 0 = "", 1 = "а"
/// DSTU 3008:2015 Style
/// -> content
/// - it (content): Content to apply the style to.
/// - skip (int): Do not show page number for this number of pages.
/// - offset (int): Adjust all page numbers by this amount.
#let dstu-style(
it,
skip: 0,
offset: 0,
) = {
// General Styling {{{1
set page(
paper: "a4",
number-align: top + right,
margin: (top: 20mm, right: 10mm, bottom: 20mm, left: 25mm),
numbering: (i, ..) => if i > skip { numbering("1", i + offset) },
)
set text(
lang: "uk",
size: 14pt,
hyphenate: false,
font: ("Times New Roman", "Liberation Serif"),
)
set par(
justify: true,
spacing: spacing,
leading: spacing,
first-line-indent: (amount: 1.25cm, all: true),
)
set block(spacing: spacing)
set underline(evade: false)
// Enums & Lists {{{1
// First level
set enum(
indent: 1.25cm,
body-indent: 0.5cm,
numbering: i => { num-to-alpha.at(i) + ")" },
)
// Second level and further nesting
show enum: it => {
set enum(indent: 0em, numbering: "1)")
it
}
// Lists are not intended for multiple levels, use `enum`
set list(indent: 1.35cm, body-indent: 0.5cm, marker: [--])
// Figures {{{1
show figure: it => {
v(spacing * 2, weak: true)
it
v(spacing * 2, weak: true)
}
set figure.caption(separator: [ -- ])
show figure.where(kind: table): set figure.caption(position: top)
show figure.caption.where(kind: table): set align(left)
// Numbering {{{1
show heading.where(level: 1): it => {
counter(math.equation).update(0)
counter(figure.where(kind: raw)).update(0)
counter(figure.where(kind: image)).update(0)
counter(figure.where(kind: table)).update(0)
it
}
set figure(numbering: i => numbering("1.1", counter(heading).get().at(0), i))
set math.equation(
numbering: i => numbering(
"(1.1)",
counter(heading).get().at(0),
i,
),
)
// Headings {{{1
set heading(numbering: "1.1")
show heading: it => if it.level == 1 {
set align(center)
set text(size: 14pt, weight: "semibold")
pagebreak(weak: true)
upper(it)
v(spacing * 2, weak: true)
} else {
set text(size: 14pt, weight: "regular")
v(spacing * 2, weak: true)
block(width: 100%, spacing: 0em)[
#h(1.25cm)
#counter(heading).display(auto)
#it.body
]
v(spacing * 2, weak: true)
}
show heading.where(level: 3): it => {
set text(size: 14pt, weight: "regular")
v(spacing * 2, weak: true)
block(width: 100%, spacing: 0em)[
#h(1.25cm)
#counter(heading).display(it.numbering)
#it.body
]
v(spacing * 2, weak: true)
}
// listings {{{3
show raw.where(block: true): it => {
let new_spacing = 0.5em
set block(spacing: new_spacing)
set par(spacing: new_spacing, leading: new_spacing)
set text(
size: 11pt,
weight: "semibold",
font: ("Courier New", "Liberation Mono"),
)
v(spacing * 2.5, weak: true)
pad(it, left: 1.25cm)
v(spacing * 2.5, weak: true)
}
it
// }}}
}
/// DSTU 3008:2015 Appendices Style
/// -> content
/// - it (content): Content to apply the style to.
#let appendices-style(it) = /* {{{ */ {
// Numbering
counter(heading).update(0)
set heading(
numbering: (i, ..n) => (
upper(num-to-alpha.at(i)) + numbering(".1.1", ..n)
),
)
set figure(numbering: i => [#upper(num-to-alpha.at(counter(heading).get().at(0))).#i])
set math.equation(numbering: i => [(#upper(num-to-alpha.at(counter(heading).get().at(0))).#i)])
// Headings
show heading: it => if it.level == 1 {
set align(center)
set text(size: 14pt, weight: "regular")
pagebreak(weak: true)
text(weight: "bold")[ДОДАТОК #counter(heading).display(auto)]
linebreak()
it.body
v(spacing * 2, weak: true)
} else {
set text(size: 14pt, weight: "regular")
v(spacing * 2, weak: true)
block(width: 100%, spacing: 0em)[
#h(1.25cm)
#counter(heading).display(auto)
#it.body
]
v(spacing * 2, weak: true)
}
it
} // }}}
// Coursework template {{{1
/// DSTU 3008:2015 Template for NURE
/// -> content
/// - doc (content): Content to apply the template to.
/// - title (str): Title of the document.
/// - subject (str): Subject short name.
/// - authors ((name: str, full_name_gen: str, variant: int, course: int, semester: int, group: str, gender: str),): List of authors.
/// - mentors ((name: str, degree: str),): List of mentors.
/// - edu_program (str): Education program shorthand.
/// - task_list (done_date: datetime, initial_date: datetime, source: (content | str), content: (content | str), graphics: (content | str)): Task list object.
/// - calendar_plan ( plan_table: (content | str), approval_date: datetime): Calendar plan object.
/// - abstract (keywords: (str, ), text: (content | str)): Abstract object.
/// - bib_path path: Path to the bibliography yaml file.
/// - appendices (content): Content with appendices.
#let coursework(
doc,
title: none,
subject: none,
university: "ХНУРЕ",
author: (),
mentors: (),
edu_program: none,
task_list: (),
calendar_plan: (),
abstract: (),
bib_path: none,
appendices: (),
) = {
set document(title: title, author: author.name)
show: dstu-style.with(skip: 1)
let bib-count = state("citation-counter", ())
show cite: it => {
it
bib-count.update(((..c)) => (..c, it.key))
}
show bibliography: it => {
set text(size: 0pt)
it
}
let head_mentor = mentors.at(0)
let uni = universities.at(university)
let edu_prog = uni.edu_programs.at(edu_program)
// page 1 {{{2
[
#set align(center)
МІНІСТЕРСТВО ОСВІТИ І НАУКИ УКРАЇНИ\
#upper(uni.name)
\
Кафедра #edu_prog.department_gen
\
ПОЯСНЮВАЛЬНА ЗАПИСКА\
ДО КУРСОВОЇ РОБОТИ\
з дисципліни: "#uni.subjects.at(subject, default: "NONE")"\
Тема роботи: "#title"
\ \ \
#columns(2, gutter: 4cm)[
#set align(left)
#if author.gender == "m" { [Виконав\ ] } else { [Виконала\ ] } ст. гр. #edu_program\-#author.group
\
Керівник:\
#head_mentor.degree
\
Робота захищена на оцінку
\
Комісія:\
#for mentor in mentors {
[#mentor.degree\
]
}
#colbreak()
#set align(left)
\
#author.name
\ \
#head_mentor.name
\
#underline(" " * 35)
\ \
#for mentor in mentors {
[#mentor.name\
]
}
]
#v(1fr)
Харків -- #task_list.done_date.display("[year]")
#pagebreak()
]
// page 2 {{{2
{
uline[#uni.name]
linebreak()
linebreak()
grid(
columns: (100pt, 1fr),
bold[
Кафедра
Дисципліна
Спеціальність
],
{
uline(align: left, edu_prog.department_gen)
linebreak()
uline(align: left, uni.subjects.at(subject))
linebreak()
uline(align: left, [#edu_prog.code #edu_prog.name_long])
},
)
grid(
columns: (1fr, 1fr, 1fr),
gutter: 0.3fr,
[#bold[Курс] #uline(author.course)],
[#bold[Група] #uline([#edu_program\-#author.group])],
[#bold[Семестр] #uline(author.semester)],
)
linebreak()
linebreak()
linebreak()
align(center, bold[ЗАВДАННЯ \ на курсову роботу студента])
linebreak()
uline(align: left)[_#author.full_name_gen _]
linebreak()
linebreak()
bold[\1. Тема роботи:]
uline[#title.]
linebreak()
{
bold[\2. Строк здачі закінченої роботи:]
uline(task_list.done_date.display("[day].[month].[year]"))
hfill(10fr)
}
linebreak()
bold[\3. Вихідні дані для роботи:]
uline(task_list.source)
linebreak()
bold[\4. Зміст розрахунково-пояснювальної записки:]
uline(task_list.content)
linebreak()
bold[\5. Перелік графічного матеріалу:]
uline(task_list.graphics)
linebreak()
{
bold[\6. Дата видачі завдання:]
uline(task_list.initial_date.display("[day].[month].[year]"))
hfill(10fr)
}
pagebreak()
}
// page 3 {{{2
{
align(center, bold[КАЛЕНДАРНИЙ ПЛАН])
set par(first-line-indent: 0pt)
linebreak()
calendar_plan.plan_table
linebreak()
grid(
columns: (5fr, 5fr),
grid(
columns: (1fr, 2fr, 1fr),
gutter: 0.2fr,
[
Студент \
Керівник \
#align(center)["#underline[#calendar_plan.approval_date.day()]"]
],
[
#uline(align: center, []) \
#uline(align: center, []) \
#uline(align: center, month_gen(calendar_plan.approval_date.month()))
],
[
\ \
#underline[#calendar_plan.approval_date.year()] р.
],
),
[
#author.name, \
#head_mentor.degree
#head_mentor.name.
],
)
pagebreak()
}
// page 4 {{{2
[
#align(center, bold[РЕФЕРАТ]) \
#context [
#let pages = counter(page).final().at(0)
#let images = query(figure.where(kind: image)).len()
#let tables = query(figure.where(kind: table)).len()
#let bibs = bib-count.final().dedup().len()
/* TODO: why this stopped working?
#let tables = counter(figure.where(kind: table)).final().at(0)
#let images = counter(figure.where(kind: image)).final().at(0)*/
#let counters = ()
#if pages != 0 { counters.push[#pages с.] }
#if tables != 0 { counters.push[#tables табл.] }
#if images != 0 { counters.push[#images рис.] }
#if bibs != 0 { counters.push[#bibs джерел] }
Пояснювальна записка до курсової роботи: #counters.join(", ").
]
\
#{
let keywords = abstract.keywords.map(upper)
let is_cyrillic = word => word.split("").any(char => ("А" <= char and char <= "я"))
let n = keywords.len()
for i in range(n) {
for j in range(0, n - i - 1) {
if (
(
not is_cyrillic(keywords.at(j)) and is_cyrillic(keywords.at(j + 1))
)
or (
is_cyrillic(keywords.at(j)) == is_cyrillic(keywords.at(j + 1)) and keywords.at(j) > keywords.at(j + 1)
)
) {
(keywords.at(j), keywords.at(j + 1)) = (
keywords.at(j + 1),
keywords.at(j),
)
}
}
}
keywords.join(", ")
}
\
#abstract.text
]
// page 5 {{{2
outline(
title: [
ЗМІСТ
#v(spacing * 2, weak: true)
],
depth: 2,
indent: auto,
)
doc
// bibliography {{{2
{
heading(depth: 1, numbering: none)[Перелік джерел посилання]
bibliography(
bib_path,
style: "ieee",
full: true,
title: none,
)
let bib_data = yaml(bib_path)
let format-entry(citation) = {
if (citation.type == "Web") {
let date_array = citation.url.date.split("-")
let date = datetime(
year: int(date_array.at(0)),
month: int(date_array.at(1)),
day: int(date_array.at(2)),
)
[
#citation.title.
#citation.author.
URL: #citation.url.value (дата звернення: #date.display("[day].[month].[year]")).
]
} else if citation.type == "Book" [
#citation.author
#citation.title.
#citation.publisher,
#citation.date.
#citation.page-total c.
] else [
UNSUPPORTED BIBLIOGRAPHY ENTRY TYPE, PLEASE OPEN AN ISSUE
]
}
show enum.item: it => {
set par(first-line-indent: 0pt)
box(width: 1.25cm)
box(width: 1em + 0.5cm)[#it.number.]
it.body
linebreak()
}
context {
for (i, citation) in query(ref.where(element: none)).map(r => str(r.target)).dedup().enumerate() {
enum.item(
i + 1,
format-entry(bib_data.at(citation)),
)
}
}
}
appendices-style(appendices)
}
// Practice and Laboratory works template {{{1
/// DSTU 3008:2015 Template for NURE
/// -> content
/// - doc (content): Content to apply the template to.
/// - edu_program (str): Education program shorthand.
/// - doctype ("ЛБ" | "ПЗ" | str): Document type.
/// - title (str or none): Title of the document. Optional.
/// - subject (str): Subject shorthand.
/// - worknumber (int or none): Number of the work. Optional.
/// - authors ((name: str, full_name_gen: str, group: str, gender: str, variant: int or none),): List of authors.
/// - mentors ((name: str, degree: str, gender: str or none),): List of mentors. Optional.
/// - chapters (): List of file names in chapters/ subdirectory. Optional.
#let pz-lb(
doc,
university: "ХНУРЕ",
edu_program: none,
doctype: none,
title: none,
subject: none,
worknumber: none,
authors: (),
mentors: (),
chapters: (),
) = {
assert.ne(edu_program, none, message: "Missing argument: \"edu_program\"")
assert.ne(doctype, none, message: "Missing argument: \"doctype\"")
assert.ne(subject, none, message: "Missing argument: \"subject\"")
set document(title: title, author: authors.at(0).name)
show: dstu-style.with(skip: 1)
let uni = universities.at(university)
let edu_prog = uni.edu_programs.at(edu_program)
// page 1 {{{2
align(center)[
МІНІСТЕРСТВО ОСВІТИ І НАУКИ УКРАЇНИ \
#upper(uni.name)
\ \
Кафедра #edu_prog.department_gen
\ \ \
#if doctype == "ЛБ" [Звіт \ з лабораторної роботи] else if (
doctype == "ПЗ"
) [Звіт \ з практичної роботи] else [#doctype]
#if worknumber != none {
context counter(heading).update(worknumber - if title == none { 0 } else { 1 })
[№#worknumber]
} else if title != none and worknumber != none {
context counter(heading).update(1)
}
з дисципліни: "#uni.subjects.at(subject)"
#if title != none [з теми: "#eval(title, mode: "markup")"]
\ \ \ \
#columns(2)[
#set align(left)
#set par(first-line-indent: 0pt)
#if authors.len() == 1 {
let author = authors.at(0)
if author.gender == "m" [Виконав:\ ] else [Виконала:\ ]
[
здобувач освіти першого (бакаларвського) рівня освіти гр. #edu_program\-#author.group\
#author.name\
]
if (
"variant" in author.keys() and author.variant != none
) [Варіант: №#author.variant]
} else if authors.len() > 1 [
Виконали:\
ст. гр. #edu_program\-#authors.at(0).group\
#for author in authors [#author.name\ ]
]
#colbreak()
#set align(right)
#if type(mentors) == array {
if mentors.len() == 1 {
let mentor = mentors.at(0)
if "gender" in mentor.keys() {
if mentor.gender == "m" [Перевірив:\ ] else if (
mentor.gender == "f"
) [Перевірила:\ ]
} else [Перевірили:\ ]
if (
"degree" in mentor.keys() and mentor.degree != none
) [#mentor.degree\ ]
[#mentor.name\ ]
} else if mentors.len() > 1 [
Перевірили:\
#for mentor in mentors {
[
#mentor.degree\
#mentor.name\
]
}
]
}
]
#v(1fr)
Харків -- #datetime.today().display("[year]")
]
pagebreak(weak: true)
if title != none [#heading(eval(title, mode: "markup"))]
doc
chapters.map(chapter => include "/chapters/" + str(chapter) + ".typ").join()
}
// vim:sts=2:sw=2:fdm=marker:cms=/*%s*/

24
pz1/validate-all.fish Executable file
View File

@@ -0,0 +1,24 @@
#!/usr/bin/env fish
set -l entities freight vehicle route
echo '=== WELL-FORMEDNESS ==='
for entity in $entities
echo "validating $entity.xml for validity (well-formedness)"
xmllint --noout "$entity"s.xml
if test $status -ne 4 # return code 4 - document isn't well-formed
echo "$entity"s.xml is valid!
end
end
echo '=== XML SCHEMA COMPLIANCE ==='
for entity in $entities
echo "validating $entity.xml for compliance with $entity-schema.xsd"
xmllint --noout --schema $entity-schema.xsd "$entity"s.xml
end
echo '=== JSON SCHEMA COMPLIANCE ==='
for entity in $entities
echo "validating $entity.json for compliance with $entity-schema.json"
ajv validate -s "$entity-schema.json" -d "$entity"s.json --spec=draft2020
end

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

59
pz1/vehicle-schema.json Normal file
View File

@@ -0,0 +1,59 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://nure.ua/itroi/vehicle-schema.json",
"title": "Vehicles management schema",
"description": "Describes domain objects of vehicles",
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "integer",
"minimum": 1,
"maximum": 4294967295
},
"brand": {
"type": "string",
"minLength": 2,
"maxLength": 64
},
"model": {
"type": "string",
"minLength": 1,
"maxLength": 128
},
"license_plate": {
"type": "string",
"pattern": "^[A-Z]{2}[0-9]{4}[A-Z]{2}$",
"minLength": 8,
"maxLength": 8
},
"year": {
"type": "integer",
"minimum": 1980
},
"capacity_kg": {
"type": "number",
"minimum": 100,
"exclusiveMaximum": 4294967296
},
"status": {
"type": "string",
"enum": [
"AVAILABLE",
"IN_TRANSIT",
"MAINTENANCE"
]
}
},
"required": [
"id",
"brand",
"model",
"license_plate",
"year",
"capacity_kg",
"status"
]
}
}

76
pz1/vehicle-schema.xsd Normal file
View File

@@ -0,0 +1,76 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="https://nure.ua/itroi/vehicle-schema"
xmlns:tns="https://nure.ua/itroi/vehicle-schema"
elementFormDefault="qualified">
<xs:element name="vehicles" type="tns:VehicleArray"/>
<xs:complexType name="VehicleArray">
<xs:sequence>
<xs:element name="vehicle" type="tns:Vehicle" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="Vehicle">
<xs:all>
<xs:element name="id">
<xs:simpleType>
<xs:restriction base="xs:integer">
<xs:minInclusive value="1"/>
<xs:maxInclusive value="4294967296"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="brand">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:minLength value="2"/>
<xs:maxLength value="64"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="model">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:minLength value="1"/>
<xs:maxLength value="128"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="license_plate">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:pattern value="[A-Z]{2}[0-9]{4}[A-Z]{2}"/>
<xs:minLength value="8"/>
<xs:maxLength value="8"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="year">
<xs:simpleType>
<xs:restriction base="xs:integer">
<xs:minInclusive value="1980"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="capacity_kg">
<xs:simpleType>
<xs:restriction base="xs:decimal">
<xs:minInclusive value="100"/>
<xs:maxExclusive value="4294967296"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="status">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="AVAILABLE"/>
<xs:enumeration value="IN_TRANSIT"/>
<xs:enumeration value="MAINTENANCE"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:all>
</xs:complexType>
</xs:schema>

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

29
pz1/vehicles.json Normal file
View File

@@ -0,0 +1,29 @@
[
{
"id": 1,
"brand": "Volvo",
"model": "FH16",
"license_plate": "AX6789BC",
"year": 2022,
"capacity_kg": 25500.5,
"status": "AVAILABLE"
},
{
"id": 2,
"brand": "Scania",
"model": "R 450",
"license_plate": "CE1122DF",
"year": 2019,
"capacity_kg": 24000,
"status": "IN_TRANSIT"
},
{
"id": 3,
"brand": "Mercedes-Benz",
"model": "Actros",
"license_plate": "IO5432GH",
"year": 2020,
"capacity_kg": 26000,
"status": "MAINTENANCE"
}
]

33
pz1/vehicles.xml Normal file
View File

@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="vehicles.xsl"?>
<vehicles xmlns="https://nure.ua/itroi/vehicle-schema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://nure.ua/itroi/vehicle-schema vehicle-schema.xsd">
<vehicle>
<id>1</id>
<brand>Volvo</brand>
<model>FH16</model>
<license_plate>AX6789BC</license_plate>
<year>2022</year>
<capacity_kg>25500.5</capacity_kg>
<status>AVAILABLE</status>
</vehicle>
<vehicle>
<brand>Scania</brand>
<id>2</id>
<model>R 450</model>
<license_plate>CE1122DF</license_plate>
<year>2019</year>
<capacity_kg>24000</capacity_kg>
<status>IN_TRANSIT</status>
</vehicle>
<vehicle>
<id>3</id>
<brand>Mercedes-Benz</brand>
<model>Actros</model>
<license_plate>IO5432GH</license_plate>
<year>2020</year>
<capacity_kg>26000</capacity_kg>
<status>MAINTENANCE</status>
</vehicle>
</vehicles>

69
pz1/vehicles.xsl Normal file
View File

@@ -0,0 +1,69 @@
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:vs="https://nure.ua/itroi/vehicle-schema">
<xsl:output method="html" indent="yes" encoding="UTF-8"/>
<xsl:template match="/">
<html>
<head>
<title>Автопарк</title>
<link rel="stylesheet" type="text/css" href="index.css"/>
<script>
function filterVehicles() {
var selectedStatus = document.getElementById('statusFilter').value;
var rows = document.querySelectorAll('#vehicleTable tbody tr');
rows.forEach(function(row) {
var status = row.getAttribute('data-status');
if (selectedStatus === 'ALL' || status === selectedStatus) {
row.classList.remove('hidden');
} else {
row.classList.add('hidden');
}
});
}
</script>
</head>
<body>
<h1>Aвтопарк</h1>
<div class="filter-container">
<label for="statusFilter">Фільтрувати за статусом:</label>
<select id="statusFilter" onchange="filterVehicles()">
<option value="ALL">Всі статуси</option>
<option value="AVAILABLE">AVAILABLE</option>
<option value="IN_TRANSIT">IN_TRANSIT</option>
<option value="MAINTENANCE">MAINTENANCE</option>
</select>
</div>
<table id="vehicleTable">
<thead>
<tr>
<th>ID</th>
<th>Марка та Модель</th>
<th>Номерний знак</th>
<th>Рік</th>
<th>Вантажопідйомність (кг)</th>
<th>Статус</th>
</tr>
</thead>
<tbody>
<xsl:apply-templates select="vs:vehicles/vs:vehicle"/>
</tbody>
</table>
</body>
</html>
</xsl:template>
<xsl:template match="vs:vehicle">
<tr data-status="{vs:status}">
<td><xsl:value-of select="vs:id"/></td>
<td><xsl:value-of select="concat(vs:brand, ' ', vs:model)"/></td>
<td><xsl:value-of select="vs:license_plate"/></td>
<td><xsl:value-of select="vs:year"/></td>
<td><xsl:value-of select="vs:capacity_kg"/></td>
<td><xsl:value-of select="vs:status"/></td>
</tr>
</xsl:template>
</xsl:stylesheet>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,121 @@
#import "@local/nure:0.1.0": *
#show: pz-lb.with(
..yaml("doc.yaml"),
worknumber: 1,
title: "РОЗРОБКА СПЕЦИФІКАЦІЙ ВЗАЄМОДІЇ ПІДСИСТЕМ РОЗПОДІЛЕНОГО ПРОГРАМНОГО ЗАСТОСУВАННЯ",
bib_array: bytes(read("bibl.yml")),
)
== Мета роботи
#v(-spacing)
Вивчення можливостей мов XML та JSON для опису даних предметної області.
+ Одержати практичні навички по створенню XML та JSON-документів, що представляють дані заданої предметної області.
+ Одержати практичні навички по створенню користувацької мови розмітки для опису та представлення даних предметної області за допомогою інструкцій мов XSD та JSON-schema.
+ Ознайомлення з функціональними можливостями інтегрованого середовища розробки.
+ Одержати практичні навички створення XML та JSON -документів і їх XML та JSON-schema в інтегрованому середовищі розробки.
== Хід роботи
#v(-spacing)
Для виконання роботи було обрано тему ІС "Логістична компанія".
Після початкового аналізу було виділено три основні сутності: транспортні засоби, вантажі та маршрути.
Було розроблено специфікації майбутньої програми на двох мовах: XML та JSON.
XML є більш старою мовою для опису даних, але з іншого боку це означає що багато бібліотек мають довгорічну підтримку для серіалізації даних в цей формат.
XML використовує теги, обгорнуті в символи "більше, ніж", та "менше, ніж" для опису атрибутів. В цьому плані вона сильно програє JSON, бо
в форматі опису об'єктів JavaScript не треба вказувати теги для опису атрибутів даних, достатньо лише вказати ім'я атрибуту і його значення.
З іншого боку, це робить неможливим додавання анотацій до даних, тобто щоб вказати обмеження деякого значення в JSON schema, доводиться робити це окремими атрибутами,
що може виглядати не дуже зрозуміло для людей, які звикли до роботи з XML-схемами.
Повний код для XML та JSON схем та документів наведено нижче.
#show figure: set block(breakable: true)
#set raw(block: true)
#{
set raw(lang: "json")
figure(raw(read("vehicle-schema.json")), caption: [JSON-cхема сутностей транспортних засобів])
figure(raw(read("freight-schema.json")), caption: [JSON-cхема сутностей вантажів])
figure(raw(read("route-schema.json")), caption: [JSON-cхема сутностей маршрутів])
figure(raw(read("vehicles.json")), caption: [JSON cутності транспортних засобів])
figure(raw(read("freights.json")), caption: [JSON cутності вантажів])
figure(raw(read("routes.json")), caption: [JSON cутності маршрутів])
}
#{
set raw(lang: "xml")
figure(raw(read("vehicle-schema.xsd")), caption: [XSD-cхема сутностей транспортних засобів])
figure(raw(read("freight-schema.xsd")), caption: [XSD-cхема сутностей вантажів])
figure(raw(read("route-schema.xsd")), caption: [XSD-cхема сутностей маршрутів])
figure(raw(read("vehicles.xml")), caption: [XML cутності транспортних засобів])
figure(raw(read("freights.xml")), caption: [XML cутності вантажів])
figure(raw(read("routes.xml")), caption: [XML cутності маршрутів])
}
Всі документи було перевірено на коректність та валідність відповідно до їхніх схем.
Валідацію було реалізовано за допомогою розробленого скрипта та валідаторів `xmllint` (входить до складу бібліотеки `libxml2` @libxml2) та `ajv` @ajv
#figure(image("./all-validate.png", width: 80%), caption: [Результат валідації всіх документів])
Також, було розроблено XSLT документи, що дозволяють зручно переглядати усі XML документи та фільтрувати сутності за статусом (див. @rxslt та @rxslt-f).
#figure(
image("./routes-xslt.png", width: 80%),
caption: [XML документ з маршрутами, до якого застосовано XSLT документ],
) <rxslt>
#figure(image("./routes-xslt-filtered.png", width: 80%), caption: [Фільтрація маршрутів]) <rxslt-f>
Код розроблених XSLT-документів наведений нижче
#{
set raw(lang: "xslt")
figure(raw(read("vehicles.xsl")), caption: [Стилі для XML сутностей транспорту])
figure(raw(read("freights.xsl")), caption: [Стилі для XML сутностей вантажів])
figure(raw(read("routes.xsl")), caption: [Стилі для XML сутностей маршрутів])
set raw(lang: "css")
figure(raw(read("index.css")), caption: [CSS документ, що використовується для стилізації XSLT документів])
}
Додатково було реалізовано програмні інтерфейси мовою Java. На лістингу, наведеному нижче,
описано класи, що існують для реалізації бізнес-логіки.
#{
figure(
raw(
"
public class VehicleService {
public List<Vehicle> getAll() { }
public Vehicle add(Vehicle veh) { }
public Optional<Vehicle> getById(long id) { }
public Vehicle update(long id, Vehicle newVehicle) { }
public Vehicle delete(long id) { }
}
public class FreightService {
public List<Freight> getAll() { }
public Freight add(Freight freight) { }
public Optional<Freight> getById(long id) { }
public Freight update(long id, Freight newFreight) { }
public Freight delete(long id) { }
}
public class RouteService {
public List<Route> getAll() { }
public Optional<Route> getById(long id) { }
public Route add(Route route) { }
public Route getByFreightId(long freightId) { }
public Route getByVehicleId(long vehicleId) { }
public Route update(long id, Route newRoute) { }
public Route delete(long id) { }
}
",
lang: "java",
),
caption: [Програмні інтерфейси, що задають специфікації веб-сервісів],
)
}
== Висновки
Під час виконання практичної роботи, було розроблено JSON- та XML- схеми та моделі, що відображають сутності предметної області.
Також, було перевірено валідність розроблених документів відповідно до схеми.
Було описано програмні інтерфейси мовою Java, що задають специфікації веб-сервісів.

25
pz2/all-files Normal file
View File

@@ -0,0 +1,25 @@
/home/dxrkness/Downloads/git-projects/itroi/build.gradle.kts
/home/dxrkness/Downloads/git-projects/itroi/gradle/libs.versions.toml
/home/dxrkness/Downloads/git-projects/itroi/gradle.properties
/home/dxrkness/Downloads/git-projects/itroi/settings.gradle.kts
/home/dxrkness/Downloads/git-projects/itroi/src/main/java/ua/com/dxrkness/LogisticsApplication.java
/home/dxrkness/Downloads/git-projects/itroi/src/main/java/ua/com/dxrkness/controller/FreightController.java
/home/dxrkness/Downloads/git-projects/itroi/src/main/java/ua/com/dxrkness/controller/RouteController.java
/home/dxrkness/Downloads/git-projects/itroi/src/main/java/ua/com/dxrkness/controller/VehicleController.java
/home/dxrkness/Downloads/git-projects/itroi/src/main/java/ua/com/dxrkness/model/Freight.java
/home/dxrkness/Downloads/git-projects/itroi/src/main/java/ua/com/dxrkness/model/Identifiable.java
/home/dxrkness/Downloads/git-projects/itroi/src/main/java/ua/com/dxrkness/model/Route.java
/home/dxrkness/Downloads/git-projects/itroi/src/main/java/ua/com/dxrkness/model/Vehicle.java
/home/dxrkness/Downloads/git-projects/itroi/src/main/java/ua/com/dxrkness/package-info.java
/home/dxrkness/Downloads/git-projects/itroi/src/main/java/ua/com/dxrkness/repository/CrudRepository.java
/home/dxrkness/Downloads/git-projects/itroi/src/main/java/ua/com/dxrkness/repository/FreightRepository.java
/home/dxrkness/Downloads/git-projects/itroi/src/main/java/ua/com/dxrkness/repository/RouteRepository.java
/home/dxrkness/Downloads/git-projects/itroi/src/main/java/ua/com/dxrkness/repository/VehicleRepository.java
/home/dxrkness/Downloads/git-projects/itroi/src/main/java/ua/com/dxrkness/service/FreightService.java
/home/dxrkness/Downloads/git-projects/itroi/src/main/java/ua/com/dxrkness/service/PopulateService.java
/home/dxrkness/Downloads/git-projects/itroi/src/main/java/ua/com/dxrkness/service/RouteService.java
/home/dxrkness/Downloads/git-projects/itroi/src/main/java/ua/com/dxrkness/service/VehicleService.java
/home/dxrkness/Downloads/git-projects/itroi/src/main/resources/application.yaml
/home/dxrkness/Downloads/git-projects/itroi/src/test/java/ua/com/dxrkness/integration/FreightIntegrationTest.java
/home/dxrkness/Downloads/git-projects/itroi/src/test/java/ua/com/dxrkness/integration/RouteIntegrationTest.java
/home/dxrkness/Downloads/git-projects/itroi/src/test/java/ua/com/dxrkness/integration/VehicleIntegrationTest.java

1
pz2/code_java Symbolic link
View File

@@ -0,0 +1 @@
/home/dxrkness/Downloads/git-projects/itroi/

1
pz2/doc.yaml Symbolic link
View File

@@ -0,0 +1 @@
/home/dxrkness/uni/itroi/doc.yaml

0
pz2/rg Normal file
View File

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,32 @@
#import "@local/nure:0.1.0": *
#show: pz-lb.with(
..yaml("doc.yaml"),
worknumber: 2,
title: "СТВОРЕННЯ САМОСТІЙНОГО REST ВЕБ-СЕРВІСУ",
)
== Мета роботи
#v(-spacing)
Вивчення можливостей і засобів розробки REST Веб-сервісів.
== Хід роботи
#v(-spacing)
#show figure: set block(breakable: true)
#set raw(block: true)
Для виконання роботи було обрано тему ІС "Логістична компанія".
Після початкового аналізу було виділено три основні сутності: транспортні засоби, вантажі та маршрути.
#let files = (
read("all-files").split("\n").filter(str => str.len() > 0).map(str => str.slice(44)).map(str => "code_java/" + str)
)
#{
for file in files {
figure(raw(read(file)))
}
}
== Висновки

1
pz3/doc.yaml Symbolic link
View File

@@ -0,0 +1 @@
/home/dxrkness/uni/itroi/doc.yaml

1
pz4/doc.yaml Symbolic link
View File

@@ -0,0 +1 @@
/home/dxrkness/uni/itroi/doc.yaml

1
pz5/doc.yaml Symbolic link
View File

@@ -0,0 +1 @@
/home/dxrkness/uni/itroi/doc.yaml

36
services Normal file
View File

@@ -0,0 +1,36 @@
-- API
-- 1. Vehicle Service
сервіс управління транспортними засобами
getAllVehicles()
addVehicle(veh)
getVehicleById(id)
updateVehicle(id, newVeh)
deleteVehicle(id)
----------------------------------------
-- 2. Freight Service
сервіс управління вантажами.
getAllFreights()
addFreight(fre)
getFreightById(id)
updateFreight(id, fre)
deleteFreight(id)
----------------------------------------
-- 3. Route Planning Service
сервіс управління маршрутами. звертається до сервісів управління вантажами та транспортними засобами для отримання відповідних даних.
getAllRoutes()
getRouteById(id)
getRouteByFreightId(freId)
getRouteByVehicleId(vehId)
addRoute(rou)
updateRoute(id, rou)
deleteRoute(id)
----------------------------------------

Binary file not shown.

View File

@@ -0,0 +1 @@
["Клієнт успішно запускається та спрямовує всі запити + + + на API Gateway","Клієнт демонструє успішний обмін даними (GET/POST) + + + з мінімум двома публічними сервісами","Коректна обробка вхідних даних: Клієнт відображає дані, отримані з мікросервісів, у зрозумілому для + + + користувача вигляді.","Реалізовано функціональність \"Перегляд (Read): Відображення повного списку замовлень та списку + + + ресторанів","Реалізовано функціональність \"Створення (Create)\": Наявність форми для створення нової сутності, яка + + успішно відправляє POST-запит.","Реалізовано функціональність \"Редагування/Видалення (Update/Delete)\" для однієї + + ключової сутності.","Складна агрегація: Клієнт демонструє агрегацію + даних з кількох сервісів.","Користувацька взаємодія: Реалізовано елементи динамічної взаємодії (наприклад, перегляд деталей + + замовлення).","Обробка каскадних операцій: Клієнт демонструє виклик операції, яка запускає каскад внутрішніх + міжсервісних викликів на бекенді.","Обробка помилок (UX): Реалізовано механізм дружнього сповіщення користувача при отриманні + + + помилки від Gateway (HTTP 4xx/5xx).","Валідація вводу (Frontend): Реалізовано базову перевірку вхідних даних на стороні клієнта перед + + відправкою запиту.","Захист від дублювання (Ідемпотентність): Реалізовано механізм запобігання дублюванню для + неідемпотентних запитів.","Дизайн та Юзабіліті: Інтерфейс є інтуїтивно зрозумілим, має логічну навігацію та адекватний + візуальний дизайн."]