add all practicals
1
code
Submodule
17
doc.yaml
Normal 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:
|
||||
BIN
pz1/all-json-schemas-validate.png
Normal file
|
After Width: | Height: | Size: 90 KiB |
BIN
pz1/all-validate.png
Normal file
|
After Width: | Height: | Size: 64 KiB |
BIN
pz1/all-xml-schemas-validate.png
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
pz1/all_files.zip
Normal file
15
pz1/bibl.yml
Normal 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
@@ -0,0 +1 @@
|
||||
../doc.yaml
|
||||
BIN
pz1/freight-json-schema-validation.png
Normal file
|
After Width: | Height: | Size: 129 KiB |
70
pz1/freight-schema.json
Normal 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
@@ -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>
|
||||
BIN
pz1/freight-xml-schema-validation.png
Normal file
|
After Width: | Height: | Size: 154 KiB |
37
pz1/freights.json
Normal 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
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
BIN
pz1/route-json-schema-validation.png
Normal file
|
After Width: | Height: | Size: 120 KiB |
58
pz1/route-schema.json
Normal 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
@@ -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>
|
||||
BIN
pz1/route-xml-schema-validation.png
Normal file
|
After Width: | Height: | Size: 150 KiB |
BIN
pz1/routes-xslt-filtered.png
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
pz1/routes-xslt.png
Normal file
|
After Width: | Height: | Size: 49 KiB |
49
pz1/routes.json
Normal 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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
BIN
pz1/vehicle-json-schema-validation.png
Normal file
|
After Width: | Height: | Size: 130 KiB |
59
pz1/vehicle-schema.json
Normal 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
@@ -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>
|
||||
BIN
pz1/vehicle-xml-schema-validation.png
Normal file
|
After Width: | Height: | Size: 150 KiB |
29
pz1/vehicles.json
Normal 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
@@ -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
@@ -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>
|
||||
15588
pz1/ІТРОІ_КНТ_22_1_Орлов_ПЗ1.pdf
Normal file
121
pz1/ІТРОІ_КНТ_22_1_Орлов_ПЗ1.typ
Normal 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
@@ -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
@@ -0,0 +1 @@
|
||||
/home/dxrkness/Downloads/git-projects/itroi/
|
||||
1
pz2/doc.yaml
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/dxrkness/uni/itroi/doc.yaml
|
||||
21439
pz2/ІТРОІ_КНТ_22_1_Орлов_ПЗ2.pdf
Normal file
32
pz2/ІТРОІ_КНТ_22_1_Орлов_ПЗ2.typ
Normal 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
@@ -0,0 +1 @@
|
||||
/home/dxrkness/uni/itroi/doc.yaml
|
||||
1
pz4/doc.yaml
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/dxrkness/uni/itroi/doc.yaml
|
||||
1
pz5/doc.yaml
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/dxrkness/uni/itroi/doc.yaml
|
||||
36
services
Normal 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)
|
||||
|
||||
----------------------------------------
|
||||
BIN
ІТРОІ_ВСІ_КРИТЕРІЇ.pdf
Normal file
BIN
ІТРОІ_ПЗ_1_Критерії оцінки проєкту таблиця JSON.pdf
Normal file
BIN
ІТРОІ_ПЗ_1_Критерії оцінки проєкту таблиця XML.pdf
Normal file
BIN
ІТРОІ_ПЗ_2_Критерії оцінки проєкту таблиця.pdf
Normal file
BIN
ІТРОІ_ПЗ_3_Критерії оцінки проєкту таблиця.pdf
Normal file
BIN
ІТРОІ_ПЗ_4_Критерії оцінки проєкту таблиця.pdf
Normal file
1
ІТРОІ_ПЗ_5_Критерії оцінки проєкту JSON.txt
Normal file
@@ -0,0 +1 @@
|
||||
["Клієнт успішно запускається та спрямовує всі запити + + + на API Gateway","Клієнт демонструє успішний обмін даними (GET/POST) + + + з мінімум двома публічними сервісами","Коректна обробка вхідних даних: Клієнт відображає дані, отримані з мікросервісів, у зрозумілому для + + + користувача вигляді.","Реалізовано функціональність \"Перегляд (Read): Відображення повного списку замовлень та списку + + + ресторанів","Реалізовано функціональність \"Створення (Create)\": Наявність форми для створення нової сутності, яка + + успішно відправляє POST-запит.","Реалізовано функціональність \"Редагування/Видалення (Update/Delete)\" для однієї + + ключової сутності.","Складна агрегація: Клієнт демонструє агрегацію + даних з кількох сервісів.","Користувацька взаємодія: Реалізовано елементи динамічної взаємодії (наприклад, перегляд деталей + + замовлення).","Обробка каскадних операцій: Клієнт демонструє виклик операції, яка запускає каскад внутрішніх + міжсервісних викликів на бекенді.","Обробка помилок (UX): Реалізовано механізм дружнього сповіщення користувача при отриманні + + + помилки від Gateway (HTTP 4xx/5xx).","Валідація вводу (Frontend): Реалізовано базову перевірку вхідних даних на стороні клієнта перед + + відправкою запиту.","Захист від дублювання (Ідемпотентність): Реалізовано механізм запобігання дублюванню для + неідемпотентних запитів.","Дизайн та Юзабіліті: Інтерфейс є інтуїтивно зрозумілим, має логічну навігацію та адекватний + візуальний дизайн."]
|
||||