Лазерная резка готова

This commit is contained in:
Arsen Mirzaev Tatyano-Muradovich 2022-02-01 18:37:46 +10:00
parent 503e25647c
commit 4c6331b5da
50 changed files with 3821 additions and 422 deletions

2
.gitignore vendored
View File

@ -1 +1 @@
./vendor vendor

View File

@ -15,7 +15,8 @@
"require": { "require": {
"php": "^8.0.0", "php": "^8.0.0",
"mirzaev/minimal": "^2.0.x-dev", "mirzaev/minimal": "^2.0.x-dev",
"twig/twig": "^3.3" "twig/twig": "^3.3",
"phpoffice/phpspreadsheet": "^1.20"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {

606
composer.lock generated
View File

@ -4,8 +4,237 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "0d3565d9ca1cb09d4e7dff2f43559d81", "content-hash": "cdf791cfa902c191370bbff40d9edc04",
"packages": [ "packages": [
{
"name": "ezyang/htmlpurifier",
"version": "v4.14.0",
"source": {
"type": "git",
"url": "https://github.com/ezyang/htmlpurifier.git",
"reference": "12ab42bd6e742c70c0a52f7b82477fcd44e64b75"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/12ab42bd6e742c70c0a52f7b82477fcd44e64b75",
"reference": "12ab42bd6e742c70c0a52f7b82477fcd44e64b75",
"shasum": ""
},
"require": {
"php": ">=5.2"
},
"type": "library",
"autoload": {
"psr-0": {
"HTMLPurifier": "library/"
},
"files": [
"library/HTMLPurifier.composer.php"
],
"exclude-from-classmap": [
"/library/HTMLPurifier/Language/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"LGPL-2.1-or-later"
],
"authors": [
{
"name": "Edward Z. Yang",
"email": "admin@htmlpurifier.org",
"homepage": "http://ezyang.com"
}
],
"description": "Standards compliant HTML filter written in PHP",
"homepage": "http://htmlpurifier.org/",
"keywords": [
"html"
],
"support": {
"issues": "https://github.com/ezyang/htmlpurifier/issues",
"source": "https://github.com/ezyang/htmlpurifier/tree/v4.14.0"
},
"time": "2021-12-25T01:21:49+00:00"
},
{
"name": "maennchen/zipstream-php",
"version": "2.1.0",
"source": {
"type": "git",
"url": "https://github.com/maennchen/ZipStream-PHP.git",
"reference": "c4c5803cc1f93df3d2448478ef79394a5981cc58"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/c4c5803cc1f93df3d2448478ef79394a5981cc58",
"reference": "c4c5803cc1f93df3d2448478ef79394a5981cc58",
"shasum": ""
},
"require": {
"myclabs/php-enum": "^1.5",
"php": ">= 7.1",
"psr/http-message": "^1.0",
"symfony/polyfill-mbstring": "^1.0"
},
"require-dev": {
"ext-zip": "*",
"guzzlehttp/guzzle": ">= 6.3",
"mikey179/vfsstream": "^1.6",
"phpunit/phpunit": ">= 7.5"
},
"type": "library",
"autoload": {
"psr-4": {
"ZipStream\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Paul Duncan",
"email": "pabs@pablotron.org"
},
{
"name": "Jonatan Männchen",
"email": "jonatan@maennchen.ch"
},
{
"name": "Jesse Donat",
"email": "donatj@gmail.com"
},
{
"name": "András Kolesár",
"email": "kolesar@kolesar.hu"
}
],
"description": "ZipStream is a library for dynamically streaming dynamic zip files from PHP without writing to the disk at all on the server.",
"keywords": [
"stream",
"zip"
],
"support": {
"issues": "https://github.com/maennchen/ZipStream-PHP/issues",
"source": "https://github.com/maennchen/ZipStream-PHP/tree/master"
},
"funding": [
{
"url": "https://opencollective.com/zipstream",
"type": "open_collective"
}
],
"time": "2020-05-30T13:11:16+00:00"
},
{
"name": "markbaker/complex",
"version": "3.0.1",
"source": {
"type": "git",
"url": "https://github.com/MarkBaker/PHPComplex.git",
"reference": "ab8bc271e404909db09ff2d5ffa1e538085c0f22"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/MarkBaker/PHPComplex/zipball/ab8bc271e404909db09ff2d5ffa1e538085c0f22",
"reference": "ab8bc271e404909db09ff2d5ffa1e538085c0f22",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0"
},
"require-dev": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
"phpcompatibility/php-compatibility": "^9.0",
"phpunit/phpunit": "^7.0 || ^8.0 || ^9.3",
"squizlabs/php_codesniffer": "^3.4"
},
"type": "library",
"autoload": {
"psr-4": {
"Complex\\": "classes/src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mark Baker",
"email": "mark@lange.demon.co.uk"
}
],
"description": "PHP Class for working with complex numbers",
"homepage": "https://github.com/MarkBaker/PHPComplex",
"keywords": [
"complex",
"mathematics"
],
"support": {
"issues": "https://github.com/MarkBaker/PHPComplex/issues",
"source": "https://github.com/MarkBaker/PHPComplex/tree/3.0.1"
},
"time": "2021-06-29T15:32:53+00:00"
},
{
"name": "markbaker/matrix",
"version": "3.0.0",
"source": {
"type": "git",
"url": "https://github.com/MarkBaker/PHPMatrix.git",
"reference": "c66aefcafb4f6c269510e9ac46b82619a904c576"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/MarkBaker/PHPMatrix/zipball/c66aefcafb4f6c269510e9ac46b82619a904c576",
"reference": "c66aefcafb4f6c269510e9ac46b82619a904c576",
"shasum": ""
},
"require": {
"php": "^7.1 || ^8.0"
},
"require-dev": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
"phpcompatibility/php-compatibility": "^9.0",
"phpdocumentor/phpdocumentor": "2.*",
"phploc/phploc": "^4.0",
"phpmd/phpmd": "2.*",
"phpunit/phpunit": "^7.0 || ^8.0 || ^9.3",
"sebastian/phpcpd": "^4.0",
"squizlabs/php_codesniffer": "^3.4"
},
"type": "library",
"autoload": {
"psr-4": {
"Matrix\\": "classes/src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mark Baker",
"email": "mark@demon-angel.eu"
}
],
"description": "PHP Class for working with matrices",
"homepage": "https://github.com/MarkBaker/PHPMatrix",
"keywords": [
"mathematics",
"matrix",
"vector"
],
"support": {
"issues": "https://github.com/MarkBaker/PHPMatrix/issues",
"source": "https://github.com/MarkBaker/PHPMatrix/tree/3.0.0"
},
"time": "2021-07-01T19:01:15+00:00"
},
{ {
"name": "mirzaev/minimal", "name": "mirzaev/minimal",
"version": "2.0.x-dev", "version": "2.0.x-dev",
@ -50,6 +279,381 @@
}, },
"time": "2021-11-12T13:20:13+00:00" "time": "2021-11-12T13:20:13+00:00"
}, },
{
"name": "myclabs/php-enum",
"version": "1.8.3",
"source": {
"type": "git",
"url": "https://github.com/myclabs/php-enum.git",
"reference": "b942d263c641ddb5190929ff840c68f78713e937"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/myclabs/php-enum/zipball/b942d263c641ddb5190929ff840c68f78713e937",
"reference": "b942d263c641ddb5190929ff840c68f78713e937",
"shasum": ""
},
"require": {
"ext-json": "*",
"php": "^7.3 || ^8.0"
},
"require-dev": {
"phpunit/phpunit": "^9.5",
"squizlabs/php_codesniffer": "1.*",
"vimeo/psalm": "^4.6.2"
},
"type": "library",
"autoload": {
"psr-4": {
"MyCLabs\\Enum\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP Enum contributors",
"homepage": "https://github.com/myclabs/php-enum/graphs/contributors"
}
],
"description": "PHP Enum implementation",
"homepage": "http://github.com/myclabs/php-enum",
"keywords": [
"enum"
],
"support": {
"issues": "https://github.com/myclabs/php-enum/issues",
"source": "https://github.com/myclabs/php-enum/tree/1.8.3"
},
"funding": [
{
"url": "https://github.com/mnapoli",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/myclabs/php-enum",
"type": "tidelift"
}
],
"time": "2021-07-05T08:18:36+00:00"
},
{
"name": "phpoffice/phpspreadsheet",
"version": "1.20.0",
"source": {
"type": "git",
"url": "https://github.com/PHPOffice/PhpSpreadsheet.git",
"reference": "44436f270bb134b4a94670f3d020a85dfa0a3c02"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/44436f270bb134b4a94670f3d020a85dfa0a3c02",
"reference": "44436f270bb134b4a94670f3d020a85dfa0a3c02",
"shasum": ""
},
"require": {
"ext-ctype": "*",
"ext-dom": "*",
"ext-fileinfo": "*",
"ext-gd": "*",
"ext-iconv": "*",
"ext-libxml": "*",
"ext-mbstring": "*",
"ext-simplexml": "*",
"ext-xml": "*",
"ext-xmlreader": "*",
"ext-xmlwriter": "*",
"ext-zip": "*",
"ext-zlib": "*",
"ezyang/htmlpurifier": "^4.13",
"maennchen/zipstream-php": "^2.1",
"markbaker/complex": "^3.0",
"markbaker/matrix": "^3.0",
"php": "^7.3 || ^8.0",
"psr/http-client": "^1.0",
"psr/http-factory": "^1.0",
"psr/simple-cache": "^1.0"
},
"require-dev": {
"dealerdirect/phpcodesniffer-composer-installer": "dev-master",
"dompdf/dompdf": "^1.0",
"friendsofphp/php-cs-fixer": "^3.2",
"jpgraph/jpgraph": "^4.0",
"mpdf/mpdf": "^8.0",
"phpcompatibility/php-compatibility": "^9.3",
"phpstan/phpstan": "^1.1",
"phpstan/phpstan-phpunit": "^1.0",
"phpunit/phpunit": "^8.5 || ^9.0",
"squizlabs/php_codesniffer": "^3.6",
"tecnickcom/tcpdf": "^6.4"
},
"suggest": {
"dompdf/dompdf": "Option for rendering PDF with PDF Writer (doesn't yet support PHP8)",
"jpgraph/jpgraph": "Option for rendering charts, or including charts with PDF or HTML Writers",
"mpdf/mpdf": "Option for rendering PDF with PDF Writer",
"tecnickcom/tcpdf": "Option for rendering PDF with PDF Writer (doesn't yet support PHP8)"
},
"type": "library",
"autoload": {
"psr-4": {
"PhpOffice\\PhpSpreadsheet\\": "src/PhpSpreadsheet"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Maarten Balliauw",
"homepage": "https://blog.maartenballiauw.be"
},
{
"name": "Mark Baker",
"homepage": "https://markbakeruk.net"
},
{
"name": "Franck Lefevre",
"homepage": "https://rootslabs.net"
},
{
"name": "Erik Tilt"
},
{
"name": "Adrien Crivelli"
}
],
"description": "PHPSpreadsheet - Read, Create and Write Spreadsheet documents in PHP - Spreadsheet engine",
"homepage": "https://github.com/PHPOffice/PhpSpreadsheet",
"keywords": [
"OpenXML",
"excel",
"gnumeric",
"ods",
"php",
"spreadsheet",
"xls",
"xlsx"
],
"support": {
"issues": "https://github.com/PHPOffice/PhpSpreadsheet/issues",
"source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/1.20.0"
},
"time": "2021-11-23T15:23:42+00:00"
},
{
"name": "psr/http-client",
"version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-client.git",
"reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/http-client/zipball/2dfb5f6c5eff0e91e20e913f8c5452ed95b86621",
"reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621",
"shasum": ""
},
"require": {
"php": "^7.0 || ^8.0",
"psr/http-message": "^1.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Http\\Client\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common interface for HTTP clients",
"homepage": "https://github.com/php-fig/http-client",
"keywords": [
"http",
"http-client",
"psr",
"psr-18"
],
"support": {
"source": "https://github.com/php-fig/http-client/tree/master"
},
"time": "2020-06-29T06:28:15+00:00"
},
{
"name": "psr/http-factory",
"version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-factory.git",
"reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/http-factory/zipball/12ac7fcd07e5b077433f5f2bee95b3a771bf61be",
"reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be",
"shasum": ""
},
"require": {
"php": ">=7.0.0",
"psr/http-message": "^1.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Http\\Message\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common interfaces for PSR-7 HTTP message factories",
"keywords": [
"factory",
"http",
"message",
"psr",
"psr-17",
"psr-7",
"request",
"response"
],
"support": {
"source": "https://github.com/php-fig/http-factory/tree/master"
},
"time": "2019-04-30T12:38:16+00:00"
},
{
"name": "psr/http-message",
"version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-message.git",
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Http\\Message\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common interface for HTTP messages",
"homepage": "https://github.com/php-fig/http-message",
"keywords": [
"http",
"http-message",
"psr",
"psr-7",
"request",
"response"
],
"support": {
"source": "https://github.com/php-fig/http-message/tree/master"
},
"time": "2016-08-06T14:39:51+00:00"
},
{
"name": "psr/simple-cache",
"version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/php-fig/simple-cache.git",
"reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b",
"reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\SimpleCache\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common interfaces for simple caching",
"keywords": [
"cache",
"caching",
"psr",
"psr-16",
"simple-cache"
],
"support": {
"source": "https://github.com/php-fig/simple-cache/tree/master"
},
"time": "2017-10-23T01:57:42+00:00"
},
{ {
"name": "symfony/polyfill-ctype", "name": "symfony/polyfill-ctype",
"version": "v1.23.0", "version": "v1.23.0",

View File

@ -20,7 +20,8 @@ final class accounts_controller extends core
* Страница профиля * Страница профиля
* *
* @param array $params * @param array $params
* @return void *
* @todo 1. При истечению срока хранения куки аутентификации почему- то калькулятор ещё думает, что я аутентифицирован (вероятно одна из кук остаётся жива)
*/ */
public function index(array $vars = []): ?string public function index(array $vars = []): ?string
{ {

View File

@ -6,6 +6,8 @@ namespace mirzaev\calculator\controllers;
use mirzaev\calculator\controllers\core; use mirzaev\calculator\controllers\core;
use mirzaev\calculator\models\calculators_model as calculators; use mirzaev\calculator\models\calculators_model as calculators;
use mirzaev\calculator\models\settings_model as settings;
use mirzaev\calculator\models\metals_model as metals;
use Twig\Loader\FilesystemLoader; use Twig\Loader\FilesystemLoader;
use Twig\Environment as view; use Twig\Environment as view;
@ -79,7 +81,7 @@ final class calculator_controller extends core
public function menu(array $vars = []): ?string public function menu(array $vars = []): ?string
{ {
// Генерация представления // Генерация представления
return $this->view->render(DIRECTORY_SEPARATOR . 'calculators' . DIRECTORY_SEPARATOR . 'modules' . DIRECTORY_SEPARATOR . 'calculators' . DIRECTORY_SEPARATOR . 'menu.html', $vars); return $this->view->render(DIRECTORY_SEPARATOR . 'calculators' . DIRECTORY_SEPARATOR . 'menu.html', $vars);
} }
/** /**
@ -95,6 +97,30 @@ final class calculator_controller extends core
return $this->view->render(DIRECTORY_SEPARATOR . 'calculators' . DIRECTORY_SEPARATOR . 'modules' . DIRECTORY_SEPARATOR . 'result.html', $vars); return $this->view->render(DIRECTORY_SEPARATOR . 'calculators' . DIRECTORY_SEPARATOR . 'modules' . DIRECTORY_SEPARATOR . 'result.html', $vars);
} }
/**
* Модуль: "марка"
*
* HTML-код со списком марок металла
*
* @param array $vars Параметры
*
* @todo 1. Если металл свой, то ничего не генерировать
*/
public function mark(array $vars = []): ?string
{
// Инициализация журнала ошибок
$vars['errors'] = ['calculators' => []];
// Инициализация списка марок
$vars['marks'] = metals::marks(empty($vars['type']) ? settings::read("default_type") : $vars['type'], $vars['errors'], $vars['errors']['calculators']);
// Инициализация значения по умолчанию
if (empty($vars['marks'])) $vars['marks'] = ['Не найдено'];
// Генерация представления
return $this->view->render(DIRECTORY_SEPARATOR . 'calculators' . DIRECTORY_SEPARATOR . 'elements' . DIRECTORY_SEPARATOR. 'metals' . DIRECTORY_SEPARATOR . 'mark.html', $vars);
}
/** /**
* Модуль: "разделитель" * Модуль: "разделитель"
* *
@ -114,11 +140,30 @@ final class calculator_controller extends core
* HTML-код с калькулятором лазерной резки * HTML-код с калькулятором лазерной резки
* *
* @param array $vars Параметры * @param array $vars Параметры
*
* @todo 1. Заголовок калькулятора должен находиться внутри элемента калькулятора
* 2. Ограничение значений полей в зависимости от выбранной марки
*/ */
public function laser(array $vars = []): ?string public function laser(array $vars = []): ?string
{ {
// Инициализация журнала ошибок
$vars['errors'] = ['calculators' => []];
// Инициализация данных калькулятора
$vars['calculators'] = ['laser' => [
'company' => settings::read('default_buyer', $vars['errors']['calculators']),
'complexity' => settings::read('default_complexity', $vars['errors']['calculators']),
'width' => (int) round((float) settings::read('default_width', $vars['errors']['calculators'])),
'height' => (int) round((float) settings::read('default_height', $vars['errors']['calculators'])),
'length' => (int) round((float) settings::read('default_length', $vars['errors']['calculators'])),
'amount' => (int) round((float) settings::read('default_amount', $vars['errors']['calculators'])),
'type' => settings::read('default_type', $vars['errors']['calculators']),
'holes' => (int) round((float) settings::read('default_holes', $vars['errors']['calculators'])),
'diameter' => (float) settings::read('default_diameter', $vars['errors']['calculators'])
]];
// Генерация представления // Генерация представления
return $this->view->render(DIRECTORY_SEPARATOR . 'calculators' . DIRECTORY_SEPARATOR . 'modules' . DIRECTORY_SEPARATOR . 'calculators' . DIRECTORY_SEPARATOR . 'laser.html', $vars); return $this->view->render(DIRECTORY_SEPARATOR . 'calculators' . DIRECTORY_SEPARATOR . 'laser.html', $vars);
} }
/** /**
@ -130,6 +175,10 @@ final class calculator_controller extends core
* *
* @todo * @todo
* 1. Отправлять данные в зависимости от разрешения (обычным пользователям только expenses) * 1. Отправлять данные в зависимости от разрешения (обычным пользователям только expenses)
* 2. Переписать журнал ошибок и написать вывод ошибок куда-нибудь
* 3. Вывод ошибок в представления
* 4. Проверка на то, что существуют поставки для характеристик вписываемых в калькулятор (в режиме прямой трансляции)
* 5. Убрать передачу цены работы (оставить только время работы в часах и цену за работу в час)
*/ */
public function calculate(array $vars = []): ?string public function calculate(array $vars = []): ?string
{ {
@ -145,11 +194,11 @@ final class calculator_controller extends core
foreach ($calculators as $i => $calculator) { foreach ($calculators as $i => $calculator) {
// Перебор калькуляторов // Перебор калькуляторов
foreach (['type'] as $parameter) { foreach (['calculator'] as &$parameter) {
// Перебор мета-параметров // Перебор мета-параметров
// Инициализация общего параметра // Инициализация общего параметра
extract([$parameter => $calculator[$parameter] ?? null]); $type = $calculator[$parameter];
// Инициализация параметра для обработчика калькулятора // Инициализация параметра для обработчика калькулятора
unset($calculator[$parameter]); unset($calculator[$parameter]);
@ -174,17 +223,18 @@ final class calculator_controller extends core
// Перенос остальных параметров в буфер параметров // Перенос остальных параметров в буфер параметров
$parameters += $calculator; $parameters += $calculator;
// var_dump($parameters);
// Расчёт // Расчёт
[$machines, $managers, $engineers, $operators] = calculators::$type(...$parameters); [$machines, $managers, $engineers, $operators, $handymans, $other] = calculators::$type(...$parameters);
} }
return json_encode([ return json_encode([
'machines' => $machines, 'machines' => $machines,
'managers' => $managers, 'managers' => $managers,
'engineers' => $engineers, 'engineers' => $engineers,
'operators' => $operators 'operators' => $operators,
'handymans' => $handymans,
'other' => $other,
'errors' => $calculator['errors']
]); ]);
} }
} }

View File

@ -0,0 +1,38 @@
<?php
declare(strict_types=1);
namespace mirzaev\calculator\controllers;
use mirzaev\calculator\controllers\core;
use mirzaev\calculator\models\accounts_model as accounts;
/**
* Контроллер контактов
*
* @package mirzaev\calculator\controllers
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
*/
final class contacts_controller extends core
{
/**
* Контакты (страница)
*
* HTML-документ с контактами
*
* @param array $vars Параметры
*
* @return string HTML-докумкент
*/
public function index(array $vars = []): string
{
// Инициализация журнала ошибок
$vars['errors'] = ['contacts' => []];
// Инициализация аккаунта
$vars['account'] = accounts::account($vars['errors']['contacts']);
// Генерация представления
return $this->view->render(DIRECTORY_SEPARATOR . 'contacts' . DIRECTORY_SEPARATOR . 'index.html', $vars);
}
}

View File

@ -17,7 +17,7 @@ use Twig\Environment as view;
*/ */
final class errors_controller extends core final class errors_controller extends core
{ {
public function error404() public function error404(): string
{ {
// Запись кода ответа // Запись кода ответа
http_response_code(404); http_response_code(404);
@ -26,7 +26,7 @@ final class errors_controller extends core
return 'Не найдено (404)'; return 'Не найдено (404)';
} }
public function error500() public function error500(): string
{ {
// Запись кода ответа // Запись кода ответа
http_response_code(500); http_response_code(500);

View File

@ -0,0 +1,38 @@
<?php
declare(strict_types=1);
namespace mirzaev\calculator\controllers;
use mirzaev\calculator\controllers\core;
use mirzaev\calculator\models\accounts_model as accounts;
/**
* Контроллер журналов
*
* @package mirzaev\calculator\controllers
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
*/
final class journal_controller extends core
{
/**
* Журнал (страница)
*
* HTML-документ с журналом
*
* @param array $vars Параметры
*
* @return string HTML-докумкент
*/
public function index(array $vars = []): string
{
// Инициализация журнала ошибок
$vars['errors'] = ['journal' => []];
// Инициализация аккаунта
$vars['account'] = accounts::account($vars['errors']['journal']);
// Генерация представления
return $this->view->render(DIRECTORY_SEPARATOR . 'journal' . DIRECTORY_SEPARATOR . 'index.html', $vars);
}
}

View File

@ -9,7 +9,7 @@ use mirzaev\calculator\models\accounts_model as accounts;
use mirzaev\calculator\models\settings_model as settings; use mirzaev\calculator\models\settings_model as settings;
/** /**
* Контроллер страницы настроек * Контроллер настроек
* *
* @package mirzaev\calculator\controllers * @package mirzaev\calculator\controllers
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy> * @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
@ -22,46 +22,65 @@ final class settings_controller extends core
* HTML-документ со списком настроек * HTML-документ со списком настроек
* *
* @param array $vars Параметры * @param array $vars Параметры
*
* @return string HTML-докумкент или журнал ошибок
*/ */
public function index(array $vars = []): ?string public function index(array $vars = []): string
{ {
// Инициализация журнала ошибок // Инициализация журнала ошибок
$vars['errors'] = ['settings' => []]; $vars['errors'] = ['settings' => []];
// Инициализация аккаунта // Инициализация аккаунта
$vars['account'] = accounts::account($vars['errors']); $vars['account'] = accounts::account($vars['errors']['settings']);
// Генерация представления if (accounts::access('settings')) {
return $this->view->render(DIRECTORY_SEPARATOR . 'settings' . DIRECTORY_SEPARATOR . 'index.html', $vars); // Разрешён доступ к изменению настроек
// Инициализация настроек
$vars['settings'] = settings::translate(settings::filter(settings::read(errors: $vars['errors']['settings']), $vars['errors']['settings']), $vars['errors']['settings']);
// Генерация представления
return $this->view->render(DIRECTORY_SEPARATOR . 'settings' . DIRECTORY_SEPARATOR . 'index.html', $vars);
}
if (empty($vars['errors']['settings'])) return '';
return json_encode($vars['errors']);
} }
/** /**
* Записать * Записать
* *
* @param array $vars Параметры * @param array $vars Параметры
*
* @return string Журнал ошибок
*/ */
public function write(array $vars = []): ?bool public function write(array $vars = []): ?string
{ {
// Инициализация журнала ошибок // Инициализация журнала ошибок
$vars['errors'] = ['settings' => []]; $vars['errors'] = ['settings' => []];
// Инициализация аккаунта // Инициализация аккаунта
$vars['account'] = accounts::account($vars['errors']); $vars['account'] = accounts::account($vars['errors']['settings']);
if ($vars['account'] && $vars['account']['permissions']['settings'] ?? 0 === 1) { if ($vars['account'] && $vars['account']['permissions']['settings'] ?? 0 === 1) {
// Удалось аутентифицироваться и пройдена проверка авторизации // Удалось аутентифицироваться и пройдена проверка авторизации
// Инициализация калькуляторов из тела запроса (подразумевается, что там массивы с параметрами)
$vars['settings'] = json_decode(file_get_contents('php://input'), true);
foreach ($vars['settings'] ?? [] as $name => $value) { foreach ($vars['settings'] ?? [] as $name => $value) {
// Перебор настроек // Перебор настроек
settings::write($name, $value); // Запись в базу данных
settings::write($name, $value, $vars['errors']['settings']);
return true;
} }
return json_encode($vars['errors']);
} }
return false; http_response_code(500);
return json_encode($vars['errors']);
} }
/** /**
@ -75,7 +94,7 @@ final class settings_controller extends core
$vars['errors'] = ['settings' => []]; $vars['errors'] = ['settings' => []];
// Инициализация аккаунта // Инициализация аккаунта
$vars['account'] = accounts::account($vars['errors']); $vars['account'] = accounts::account($vars['errors']['settings']);
// Инициализация буфера вывода // Инициализация буфера вывода
$settings = []; $settings = [];
@ -83,7 +102,7 @@ final class settings_controller extends core
foreach ($vars['settings'] ?? [] as $name) { foreach ($vars['settings'] ?? [] as $name) {
// Перебор настроек // Перебор настроек
$settings[] = settings::read($name, $vars['account'] && $vars['account']['permissions']['settings'] ?? 0 === 1); $settings[] = settings::read($name, $vars['errors']['settings']);
} }
return json_encode($settings); return json_encode($settings);

View File

@ -0,0 +1,80 @@
<?php
declare(strict_types=1);
namespace mirzaev\calculator\controllers;
use mirzaev\calculator\controllers\core;
use mirzaev\calculator\models\accounts_model as accounts;
use mirzaev\calculator\models\supplies_model as supplies;
use mirzaev\calculator\models\filters\import_aluminum_filter;
use mirzaev\calculator\models\filters\import_brass_filter;
use mirzaev\calculator\models\filters\import_copper_filter;
use mirzaev\calculator\models\filters\import_stainless_steel_filter;
use mirzaev\calculator\models\filters\import_steel_filter;
use mirzaev\calculator\models\filters\import_galvanized_steel_filter;
use Exception;
/**
* Контроллер поставок
*
* @package mirzaev\calculator\controllers
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
*/
final class supplies_controller extends core
{
/**
* Записать
*
* @param array $vars Параметры
*/
public function write(array $vars = []): ?string
{
// Инициализация журнала ошибок
$vars['errors'] = ['supplies' => []];
// Инициализация аккаунта
$vars['account'] = accounts::account($vars['errors']);
if ($vars['account'] && $vars['account']['permissions']['supplies'] ?? 0 === 1) {
// Удалось аутентифицироваться и пройдена проверка авторизации
// Сохранение файла
move_uploaded_file($_FILES['supplies']['tmp_name'], $file = SUPPLIES . DIRECTORY_SEPARATOR . $_FILES['supplies']['name']);
// Запись данных из файла в базу данных
try {
@supplies::write($file, new import_aluminum_filter);
@supplies::write($file, new import_brass_filter);
@supplies::write($file, new import_copper_filter);
@supplies::write($file, new import_stainless_steel_filter);
} catch (exception $e) {
// Запись в журнал ошибок
$vars['errors']['supplies'] = [
'text' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'stack' => $e->getTrace()
];
}
try {
@supplies::write($file, new import_steel_filter, $vars['errors']['supplies']);
@supplies::write($file, new import_galvanized_steel_filter, $vars['errors']['supplies']);
} catch (exception $e) {
// Запись в журнал ошибок
$vars['errors']['supplies'] = [
'text' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'stack' => $e->getTrace()
];
}
}
// Если вернуть null покажет ошибку 404 (будет исправлено в будущих версиях mirzaev/minimal)
return json_encode($vars['errors']);
}
}

View File

@ -51,7 +51,12 @@ final class accounts_model extends core
} }
} catch (exception $e) { } catch (exception $e) {
// Запись в журнал ошибок // Запись в журнал ошибок
$errors[] = $e->getMessage(); $errors[]= [
'text' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'stack' => $e->getTrace()
];
} }
return []; return [];
@ -113,7 +118,12 @@ final class accounts_model extends core
} }
} catch (exception $e) { } catch (exception $e) {
// Запись в журнал ошибок // Запись в журнал ошибок
$errors[] = $e->getMessage(); $errors[]= [
'text' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'stack' => $e->getTrace()
];
} }
return []; return [];
@ -159,7 +169,12 @@ final class accounts_model extends core
} }
} catch (exception $e) { } catch (exception $e) {
// Запись в журнал ошибок // Запись в журнал ошибок
$errors[] = $e->getMessage(); $errors[]= [
'text' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'stack' => $e->getTrace()
];
} }
return false; return false;
@ -218,7 +233,12 @@ final class accounts_model extends core
} }
} catch (exception $e) { } catch (exception $e) {
// Запись в журнал ошибок // Запись в журнал ошибок
$errors[] = $e->getMessage(); $errors[]= [
'text' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'stack' => $e->getTrace()
];
} }
return []; return [];
@ -260,12 +280,46 @@ final class accounts_model extends core
return $response; return $response;
} catch (exception $e) { } catch (exception $e) {
// Запись в журнал ошибок // Запись в журнал ошибок
$errors[] = $e->getMessage(); $errors[]= [
'text' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'stack' => $e->getTrace()
];
} }
return []; return [];
} }
/**
* Проверить разрешение
*
* @param string $permission Разрешение
* @param int|null $id Идентификатор аккаунта
* @param array &$errors Журнал ошибок
*
* @return bool|null Статус разрешения, если оно записано
*/
public static function access(string $permission, int|null $id = null, array &$errors = []): ?bool
{
try {
// Инициализация аккаунта
$account = isset($id) ? self::read(['id' => $id], $errors) : self::account($errors);
return isset($account['permissions'][$permission]) ? (bool) $account['permissions'][$permission] : null;
} catch (exception $e) {
// Запись в журнал ошибок
$errors[]= [
'text' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'stack' => $e->getTrace()
];
}
return null;
}
/** /**
* Запись пользователя в базу данных * Запись пользователя в базу данных
* *
@ -292,7 +346,11 @@ final class accounts_model extends core
$params[':name'] = $name; $params[':name'] = $name;
} catch (exception $e) { } catch (exception $e) {
// Запись в журнал ошибок // Запись в журнал ошибок
$errors[] = $e->getMessage(); $errors[] = [
'text' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine()
];
goto end; goto end;
} }
@ -309,7 +367,11 @@ final class accounts_model extends core
$params[':email'] = $email; $params[':email'] = $email;
} catch (exception $e) { } catch (exception $e) {
// Запись в журнал ошибок // Запись в журнал ошибок
$errors[] = $e->getMessage(); $errors[] = [
'text' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine()
];
goto end; goto end;
} }
@ -325,7 +387,11 @@ final class accounts_model extends core
$params[':password'] = password_hash($password, PASSWORD_BCRYPT); $params[':password'] = password_hash($password, PASSWORD_BCRYPT);
} catch (exception $e) { } catch (exception $e) {
// Запись в журнал ошибок // Запись в журнал ошибок
$errors[] = $e->getMessage(); $errors[] = [
'text' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine()
];
goto end; goto end;
} }
@ -372,11 +438,21 @@ final class accounts_model extends core
$request->fetch(pdo::FETCH_ASSOC); $request->fetch(pdo::FETCH_ASSOC);
} catch (exception $e) { } catch (exception $e) {
// Запись в журнал ошибок // Запись в журнал ошибок
$errors[] = $e->getMessage(); $errors[] = [
'text' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'stack' => $e->getTrace()
];
} }
} catch (exception $e) { } catch (exception $e) {
// Запись в журнал ошибок // Запись в журнал ошибок
$errors[] = $e->getMessage(); $errors[]= [
'text' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'stack' => $e->getTrace()
];
} }
// Конец выполнения // Конец выполнения
@ -435,7 +511,11 @@ final class accounts_model extends core
} }
} catch (exception $e) { } catch (exception $e) {
// Запись в журнал ошибок // Запись в журнал ошибок
$errors[] = $e->getMessage(); $errors[] = [
'text' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine()
];
} }
} else { } else {
// Не найден аккаунт // Не найден аккаунт
@ -444,7 +524,12 @@ final class accounts_model extends core
} }
} catch (exception $e) { } catch (exception $e) {
// Запись в журнал ошибок // Запись в журнал ошибок
$errors[] = $e->getMessage(); $errors[]= [
'text' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'stack' => $e->getTrace()
];
} }
return isset($account) && $account ? $account : []; return isset($account) && $account ? $account : [];
@ -523,7 +608,12 @@ final class accounts_model extends core
} }
} catch (exception $e) { } catch (exception $e) {
// Запись в журнал ошибок // Запись в журнал ошибок
$errors[] = $e->getMessage(); $errors[]= [
'text' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'stack' => $e->getTrace()
];
} }
return ['hash' => $hash, 'time' => $time]; return ['hash' => $hash, 'time' => $time];

View File

@ -5,6 +5,7 @@ declare(strict_types=1);
namespace mirzaev\calculator\models; namespace mirzaev\calculator\models;
use mirzaev\calculator\models\settings_model as settings; use mirzaev\calculator\models\settings_model as settings;
use mirzaev\calculator\models\metals_model as metals;
use exception; use exception;
@ -16,171 +17,410 @@ use exception;
*/ */
final class calculators_model extends core final class calculators_model extends core
{ {
/** /**
* Рассчет калькулятора лазерной резки * Расчёт стоимости переработки за 1 тонну
*
* @param string $complexity Сложность
* @param float $lenght Толщина
* @param array &$errors Журнал ошибок
*
* @return float Стоимость переработки за 1 тонну (руб)
*/
public static function reprocessing(string $complexity, float $lenght, array &$errors = []): ?float
{
try {
return (float) match (true) {
$lenght > 0 && $lenght < 4 => settings::read('reprocessing_' . $complexity . '_1_3', $errors),
$lenght > 3 && $lenght < 7 => settings::read('reprocessing_' . $complexity . '_4_6', $errors),
$lenght > 6 && $lenght < 11 => settings::read('reprocessing_' . $complexity . '_7_10', $errors),
default => settings::read('reprocessing_' . $complexity . '_10', $errors),
}
?? 0.0;
} catch (exception $e) {
// Запись в журнал ошибок
$errors[] = $e->getMessage() . ':' . $e->getLine();
}
return 0.0;
}
/**
* Расчёт коэффициента сложности детали
*
* Влияет на скорость реза
*
* @param string $complexity Сложность детали (easy, medium, hard)
* @param int|null $area Площадь детали
* @param float|null $lenght Толщина детали
* @param array &$errors Журнал ошибок
*
* @return float Коэффициент
*
* @todo
* 1. Коэффициент исходя из типа газа (баллоны)
*/
public static function coefficient(string $complexity, ?int $area = null, ?float $lenght = null, array &$errors = []): float|false
{
try {
// Коэффициент полученный исходя из сложности детали
$coefficient = settings::read("coefficient_complexity_$complexity", $errors) ?? throw new exception("Не найдено: coefficient_complexity_$complexity");
if (
isset($area)
&& ($area <= (settings::read('coefficient_area_less', $errors) ?? throw new exception("Не найдено: coefficient_area_less"))
|| $area >= (settings::read('coefficient_area_more', $errors) ?? throw new exception("Не найдено: coefficient_area_more")))
) {
// Площадь детали не более и не менее заданных в базе данных размеров
// Прибавление коэффициента исходя из площади детали
$coefficient += settings::read('coefficient_area_degree', $errors) ?? throw new exception("Не найдено: coefficient_area_degree");
}
if (
isset($lenght)
&& ($lenght <= (settings::read('coefficient_lenght_less', $errors) ?? throw new exception("Не найдено: coefficient_lenght_less"))
|| $lenght >= (settings::read('coefficient_lenght_more', $errors) ?? throw new exception("Не найдено: coefficient_lenght_more")))
) {
// Толщина детали не более и не менее заданных в базе данных размеров
// Прибавление коэффициента исходя из толщины детали
// $coefficient += settings::read('coefficient_lenght_degree', $errors) ?? throw new exception("Не найдено: coefficient_lenght_degree");
// $coefficient -= settings::read('coefficient_lenght_degree', $errors) ?? throw new exception("Не найдено: coefficient_lenght_degree");
}
return (float) $coefficient;
} catch (exception $e) {
// Запись в журнал ошибок
$errors[] = [
'text' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'stack' => $e->getTrace()
];
}
return false;
}
/**
* Расчёт стоимости работы сотрудника
*
* @param string $position Должность (manager, engineer, operator...)
* @param string $complexity Сложность детали (easy, medium, hard)
* @param int $company Для юридического лица? Иначе как для физического
* @param array &$errors Журнал ошибок
*
* @return int Стоимость (руб)
*/
public static function employee(string $position, string $complexity, bool $company = false, array &$errors = []): array|bool
{
try {
// Инициализация категории работы для поиска данных
$type = $company ? 'entity' : 'individual';
// Инициализация всех времён работы (ч)
$min = settings::read($position . '_' . $type . '_min', $errors) ?? throw new exception('Не найдено: ' . $position . '_' . $type . '_min');
$max = settings::read($position . '_' . $type . '_max', $errors) ?? throw new exception('Не найдено: ' . $position . '_' . $type . '_max');
$average = ($min + $max) / 2;
// Инициализация времени работы
$time = (float) match ($complexity) {
'easy' => $min,
'medium' => $average,
'hard' => $max,
default => throw new exception('Неизвестный тип сложности детали')
};
// Инициализация цены за час
$hour = settings::read($position . '_' . $type . '_hour', $errors) ?? throw new exception('Не найдено: ' . $position . '_' . $type . '_hour');
return [
'time' => (float) $time,
'hour' => (float) $hour,
'cost' => $time * $hour
];
} catch (exception $e) {
// Запись в журнал ошибок
$errors[] = [
'text' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'stack' => $e->getTrace()
];
}
return false;
}
/**
* Расчёт калькулятора лазерной резки
* *
* @param bool|int|string|null $company Юридическое лицо? Или физическое лицо? * @param bool|int|string|null $company Юридическое лицо? Или физическое лицо?
* @param string|null $complexity Сложность ('easy', 'medium', 'hard') * @param string|null $complexity Сложность ('easy', 'medium', 'hard')
* @param int|string|null $width Высота (мм) * @param int|string|null $width Высота (мм)
* @param int|string|null $height Ширина (мм) * @param int|string|null $height Ширина (мм)
* @param int|string|null $lenght Длина (мм) * @param int|string|null $length Длина (мм)
* @param int|string|null $amount Количество * @param int|string|null $amount Количество
* @param string|null $metal Тип металла * @param string|null $type Тип металла
* @param string|null $mark Марка металла
* @param bool|null $out Наш металл?
* @param int|string|null $holes Количество отверстий * @param int|string|null $holes Количество отверстий
* @param int|string|null $diameter Диаметр отверстий (мм) * @param int|string|null $diameter Диаметр отверстий (мм)
* @param string|null $discount Скидка менеджера
* @param array &$errors Журнал ошибок * @param array &$errors Журнал ошибок
* *
* @return array|bool Аккаунт, если удалось аутентифицироваться * @return array|bool Аккаунт, если удалось аутентифицироваться
* *
* @todo * @todo
* 1. Значения по умолчанию брать из настроек в базе данных * 18. 1200 баллон кислород расход 1 баллон на 3 листа 4ки
* 22. Выводится результат даже если не аутентифицирован (проблема с куки)
* 29. Амортизация станка
* 30. Аренда помещения
* 31. Расходники
* 37. Проверка на то, что загружен минимум 1 калькулятор
*/ */
public static function laser( public static function laser(
bool|int|string|null $company = null, bool|int|string|null $company = null,
string|null $complexity = null, ?string $complexity = null,
int|string|null $width = null, int|string|null $width = null,
int|string|null $height = null, int|string|null $height = null,
int|string|null $length = null, float|string|null $length = null,
int|string|null $amount = null, float|string|null $amount = null,
string|null $metal = null, ?string $type = null,
?string $mark = null,
?bool $our = null,
int|string|null $holes = null, int|string|null $holes = null,
int|string|null $diameter = null, float|string|null $diameter = null,
float|string|null $discount = null,
array &$errors = [] array &$errors = []
): array { ): array {
// Инициализация журнала ошибок
$errors['laser'] ?? $errors['laser'] = [];
$i = count($errors['laser']);
$errors['laser'][$i] = [];
$errors = $errors['laser'][$i];
// Инициализация переменных для буфера вывода
$machines = $managers = $engineers = $operators = $handymans = $other = [];
try { try {
// Инициализация переменных для буфера вывода // Инициализация значений по умолчанию
$machine = $manager = $engineer = $operator = 0; $company = $company ?? throw new exception('Не передан параметр company');
$complexity = $complexity ?? throw new exception('Не передан параметр complexity');
$width = (int) $width ?? throw new exception('Не передан параметр width');
$height = (int) $height ?? throw new exception('Не передан параметр height');
$length = (float) $length ?? throw new exception('Не передан параметр length');
$amount = (float) $amount ?? throw new exception('Не передан параметр amount');
$type = $type ?? throw new exception('Не передан параметр type');
$mark = $mark ?? throw new exception('Не передан параметр mark');
$our = (bool) $our ?? true;
$holes = (int) $holes ?? throw new exception('Не передан параметр holes');
$diameter = (float) $diameter ?? throw new exception('Не передан параметр diameter');
$discount = (float) $discount ?? throw new exception('Не передан параметр discount');
// Инициализация значений по умолчанию (см. @todo) if ($width <= 0 || $height <= 0 || $length <= 0) {
$company = (bool) ($company ?? settings::read('default_buyer', $errors) === 'entity' ?? false); // Неподходящие для выполнения значения
$complexity = (string) ($complexity ?? settings::read('default_complexity', $errors) ?? 'medium');
$width = (int) ($width ?? settings::read('default_width', $errors) ?? 500);
$height = (int) ($height ?? settings::read('default_height', $errors) ?? 500);
$length = (int) ($length ?? settings::read('default_length', $errors) ?? 1);
$amount = (int) ($amount ?? settings::read('default_amount', $errors) ?? 1);
$metal = (string) ($metal ?? settings::read('default_metal', $errors) ?? 'stainless_steel');
$holes = (int) ($holes ?? settings::read('default_holes', $errors) ?? 0);
$diameter = (int) ($diameter ?? settings::read('default_diameter', $errors) ?? 0);
// Стоисмость киловатта электроэнергии throw new exception('Передан нулевой размер одной из сторон заготовки');
$electricity = settings::read('electricity', $errors) ?? 6.5; }
// Потребляемая электроэнергия станком (квт/ч) // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
$power = settings::read('laser_power', $errors) ?? 2; // $gas = 'oxygen';
$gas = 'air';
// 1 мм толщина = 220 мм/с рез у нержавеющей стали // Инициализация станка для буфера вывода
$speed = 220; $machine = [
'amount' => $amount
];
// Вычисление площади // Инициализация буфера остальных вычислений для буфера вывода
$other = [
'additive' => (float) settings::read('additive', $errors) ?? throw new exception('Не найдено: additive'),
'discount' => $discount
];
// Инициализация прибавок к наценке
$increase_300_3000 = (float) settings::read('additive_increase_300_3000', $errors) ?? throw new exception('Не найдено: additive_increase_300_3000');
if ($amount >= 300) {
// Количество заказанных деталей равно или более чем 300 шт.
for ($i = 0; $i <= $amount; ++$i) {
// Перебор по количеству изготавливаемых деталей
// Количество заказанных деталей равно или более чем 300 шт. и равно или менее чем 3000 шт.
if ($amount <= 3000) $other['additive'] += $increase_300_3000;
}
}
$other['additive'] = 1.07;
// Площадь
$area = $width * $height; $area = $width * $height;
// Коэффициент сложности // Объём
$coefficient = ($area <= (settings::read('coefficient_area_less', $errors) ?? 10000) || $area >= (settings::read('coefficient_area_more', $errors) ?? 100000) ? (settings::read('coefficient_area_degree', $errors) ?? 0.2) : 0) + match ($complexity) { $volume = $area * $length;
'easy' => (settings::read('coefficient_complexity_easy', $errors) ?? 0.8),
'medium' => (settings::read('coefficient_complexity_medium', $errors) ?? 1),
'hard' => (settings::read('coefficient_complexity_hard', $errors) ?? 1.2),
default => (settings::read('coefficient_complexity_medium', $errors) ?? 1)
};
// Расчет длины реза (мм) // Стоимость киловатта электроэнергии
eval(settings::read('laser_formula_cutting', $errors) ?? '$cutting = 3.14 * $diameter * $holes + ($width * 2 + $height * 2) * $coefficient;'); $electricity = settings::read('electricity', $errors) ?? throw new exception('Не найдено: electricity');
// Скорость реза в час (мм/с) // Потребляемая электроэнергия станком (квт/ч)
eval(settings::read('laser_formula_speed', $errors) ?? '$speed = 3600 * $speed;'); $power = settings::read('laser_power', $errors) ?? throw new exception('Не найдено: laser_power');
// Стоимость реза в час // Чтение данных листа металла (почему-то не читает если передать $length = 0.8)
eval(settings::read('laser_formula_hour', $errors) ?? '$hour = $electricity * $power;'); $list = metals::read($type, $mark, $length, $errors);
// Стоимость 1 миллиметра реза // Проверка
eval(settings::read('laser_formula_millimeter', $errors) ?? '$millimeter = $hour / $speed;'); if (empty($list['ton'])) throw new exception('Не удалось найти цену за тонну');
if (empty($list['width'])) throw new exception('Не удалось найти ширину листа');
if (empty($list['height'])) throw new exception('Не удалось найти высоту листа');
if ((int) $list['width'] < $width) throw new exception('Ширина детали крупнее чем у исходного листа');
if ((int) $list['height'] < $height) throw new exception('Высота детали крупнее чем у исходного листа');
// Cтанок (стоимость работы) // Объём листа металла
eval(settings::read('laser_formula_machine', $errors) ?? '$machine = $cutting * $millimeter * $amount;'); $list['volume'] = $list['width'] * $list['height'] * $length;
var_dump($company, $complexity, $width, $height, $length, $amount, $metal, $holes, $diameter); // Инициализация характеристик металла
$metal = [
'cut' => metals::cut($type, $gas, $length, $errors),
'weight' => metals::kg($type, $errors) * $length,
'cost' => $list['ton'] / 1000 // Цена за килограмм
];
if ($metal['cut'] <= 0 || $metal['weight'] <= 0 || $metal['cost'] <= 0) {
// Неподходящие для выполнения значения
throw new exception('Ошибка при вычислении характеристик металла');
}
if ($holes == 0 ?? $diameter == 0) {
// Не переданы данные об отверстиях
// Длина реза (мм)
$cutting = ($width * 2 + $height * 2) * self::coefficient($complexity, $area, $length, $errors);
} else {
// Переданы данные об отверстиях
// Длина реза (мм)
$cutting = (3.1416 * $diameter * $holes + $width * 2 + $height * 2) * self::coefficient($complexity, $area, $length, $errors);
}
$metal['cut'] = 65;
// Время реза одной детали (c)
$time = $cutting / $metal['cut'];
// Стоимость реза в час (руб)
$hour = $electricity * $power;
// Стоимость электроэнергии за работу станка
$machine['electricity'] = $time * $amount / 60 / 60 * $hour;
// Вес металла (кг)
$weight = $width * $height * $amount / 1000000 * $metal['weight'];
// Стоимость переработки (руб)
$other['reprocessing'] = self::reprocessing($complexity, $length, $errors) / 1000 * $weight;
// (Наш металл) Стоимость металла (руб)
if ($our) $machine['metal'] = $weight * $metal['cost'];
// Инициализация времени загрузки металла на станок
$load = (float) settings::read('handyman_metal_load_time') ?? throw new exception('Не найдено: handyman_metal_load_time');
// Инициализация стоимости часа
$hour = (float) settings::read('handyman_hour') ?? throw new exception('Не найдено: handyman_hour');
// Инициализация количества разнорабочих
$workers = settings::read('laser_handymans_amount') ?? throw new exception('Не найдено: laser_handymans_amount');
// Вычисление количества листов
for ($lists = 0; ++$lists * $list['volume'] < $volume * $amount;);
// Вычисление времени работы разнорабочих (ч)
$work = $lists * $load / 60;
// Инициализация итератора
$i = 0;
while (++$i <= $workers) {
// Перебор разнорабочих
// Инициализация разнорабочего
$handymans[$i] = [
'time' => $work, // Время работы (ч)
'hour' => $hour, // Стоимость работы в час (руб)
'cost' => $work * $hour // Стоимость работы
];
}
if ($company) { if ($company) {
// Юридическое лицо // Юридическое лицо
$min = settings::read('manager_entity_min', $errors) ?? 1; // Инициализация менеджеров
$max = settings::read('manager_entity_max', $errors) ?? 7; $managers = [static::employee('manager', $complexity, true, errors: $errors)];
$average = ($min + $max) / 2;
// Менеджер (стоимость работы) // Инициализация инженеров
$manager = (settings::read('manager_entity_hour', $errors) ?? 200) * match ($complexity) { $engineers = [static::employee('engineer', $complexity, true, errors: $errors)];
'easy' => $min,
'medium' => $average,
'hard' => $max,
default => $average
};
$min = settings::read('engineer_entity_min', $errors) ?? 2; // Инициализация стоимости работы оператора
$max = settings::read('engineer_entity_max', $errors) ?? 72; $operator = static::employee('operator', $complexity, true, errors: $errors);
$average = ($min + $max) / 2;
// Инженер (стоимость работы) // Инициализация стоимости 1 часа работы оператора
$engineer = (settings::read('engineer_entity_hour', $errors) ?? 400) * match ($complexity) { $hour = settings::read('operator_entity_hour') ?? throw new exception('Не найдено: operator_entity_hour');
'easy' => $min,
'medium' => $average,
'hard' => $max,
default => $average
};
$min = settings::read('operator_entity_min', $errors) ?? 0.33; // Инициализация операторов
$max = settings::read('operator_entity_max', $errors) ?? 16; $operators = [
$average = ($min + $max) / 2; [
'time' => [
// Оператор 'design' => $operator['time'],
$operator = (settings::read('operator_entity_hour', $errors) ?? 200) * match ($complexity) { 'machine' => ($time * $amount / 60 / 60) + $work
'easy' => $min, ],
'medium' => $average, 'hour' => $operator['hour']
'hard' => $max, ]
default => $average ];
};
} else { } else {
// Физическое лицо // Физическое лицо
$min = settings::read('manager_individual_min', $errors) ?? 1; // Инициализация менеджеров
$max = settings::read('manager_individual_max', $errors) ?? 3; $managers = [static::employee('manager', $complexity, errors: $errors)];
$average = ($min + $max) / 2;
// Менеджер (стоимость работы) // Инициализация инженеров
$manager = (settings::read('manager_individual_hour', $errors) ?? 200) * match ($complexity) { $engineers = [static::employee('engineer', $complexity, errors: $errors)];
'easy' => $min,
'medium' => $average,
'hard' => $max,
default => $average
};
$min = settings::read('manager_individual_min', $errors) ?? 2; // Инициализация данных оператора
$max = settings::read('manager_individual_max', $errors) ?? 10; $operator = static::employee('operator', $complexity, errors: $errors);
$average = ($min + $max) / 2;
// Инженер (стоимость работы) // Инициализация стоимости 1 часа работы оператора
$engineer = (settings::read('engineer_individual_hour', $errors) ?? 300) * match ($complexity) { $hour = settings::read('operator_individual_hour') ?? throw new exception('Не найдено: operator_individual_hour');
'easy' => $min,
'medium' => $average,
'hard' => $max,
default => $average
};
$min = settings::read('manager_individual_min', $errors) ?? 0.33; // Инициализация операторов
$max = settings::read('manager_individual_max', $errors) ?? 7; $operators = [
$average = ($min + $max) / 2; [
'time' => [
// Оператор (стоимость работы) 'design' => $operator['time'],
$operator = (settings::read('operator_individual_hour', $errors) ?? 200) * match ($complexity) { 'machine' => ($time * $amount / 60 / 60) + $work
'easy' => $min, ],
'medium' => $average, 'hour' => $operator['hour']
'hard' => $max, ]
default => $average ];
};
} }
// Инициализация станков
$machines = [
$machine
];
} catch (exception $e) { } catch (exception $e) {
// Запись в журнал ошибок // Запись в журнал ошибок
$errors[] = $e->getMessage(); $errors[] = [
'text' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'stack' => $e->getTrace()
];
} }
return [[$machine], [$manager], [$engineer], [$operator]]; return [$machines, $managers, $engineers, $operators, $handymans, $other];
} }
} }

View File

@ -0,0 +1,62 @@
<?php
declare(strict_types=1);
namespace mirzaev\calculator\models\filters;
use mirzaev\calculator\models\filters\import_filter_noname_1;
/**
* Фильтр импорта цен на алюминий от неизвестного поставщика под номером 1
*
* @package mirzaev\calculator\models\filters
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
*/
final class import_aluminum_filter extends import_filter_noname_1
{
/**
* Название металла
*/
public string $metal = 'aluminum';
public function readCell($columnAddress, $row, $worksheetName = '')
{
if ($row >= 16 && $row <= 17) {
// Найдены строки с маркой АД1Н
return true;
}
if ($row >= 20 && $row <= 28) {
// Найдены строки с маркой A5H
return true;
}
if ($row >= 30 && $row <= 54) {
// Найдены строки с маркой АМГ2М
return true;
}
if ($row >= 56 && $row <= 82) {
// Найдены строки с маркой АМГ3М
return true;
}
if ($row >= 84 && $row <= 105) {
// Найдены строки с маркой АМГ5М
return true;
}
if ($row >= 107 && $row <= 119) {
// Найдены строки с маркой АМГ6М
return true;
}
return false;
}
}

View File

@ -0,0 +1,38 @@
<?php
declare(strict_types=1);
namespace mirzaev\calculator\models\filters;
use mirzaev\calculator\models\filters\import_filter_noname_1;
/**
* Фильтр импорта цен на латунь от неизвестного поставщика под номером 1
*
* @package mirzaev\calculator\models\filters
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
*/
final class import_brass_filter extends import_filter_noname_1
{
/**
* Название металла
*/
public string $metal = 'brass';
public function readCell($columnAddress, $row, $worksheetName = '')
{
if ($row >= 553 && $row <= 568) {
// Найдены строки с маркой Л63
return true;
}
if ($row >= 570 && $row <= 577) {
// Найдены строки с маркой ЛС59-1
return true;
}
return false;
}
}

View File

@ -0,0 +1,32 @@
<?php
declare(strict_types=1);
namespace mirzaev\calculator\models\filters;
use mirzaev\calculator\models\filters\import_filter_noname_1;
/**
* Фильтр импорта цен на медь от неизвестного поставщика под номером 1
*
* @package mirzaev\calculator\models\filters
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
*/
final class import_copper_filter extends import_filter_noname_1
{
/**
* Название металла
*/
public string $metal = 'copper';
public function readCell($columnAddress, $row, $worksheetName = '')
{
if ($row >= 717 && $row <= 735) {
// Найдены строки с маркой М1
return true;
}
return false;
}
}

View File

@ -0,0 +1,39 @@
<?php
declare(strict_types=1);
namespace mirzaev\calculator\models\filters;
use PhpOffice\PhpSpreadsheet\Reader\IReadFilter as filter;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
/**
* Интерфейс фильтра импорта
*
* @package mirzaev\calculator\models\filters
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
*/
interface import_filter extends filter
{
/**
* Чтение ячейки
*
* @param [type] $columnAddress
* @param [type] $row
* @param string $worksheetName
*
* @return void
*/
public function readCell($columnAddress, $row, $worksheetName = '');
/**
* Фильтрация и запись прочитанных данных из EXCEL-документа
*
* @param int $supply Идентификатор поставки (для записи в БД)
* @param Worksheet $spreadsheet Таблица с прочитанными данными
* @param array &$errors Журнал ошибок
*
* @return int Количество записанных строк
*/
public function write(int $supply, Worksheet $spreadsheet, array &$errors = []): int;
}

View File

@ -0,0 +1,102 @@
<?php
declare(strict_types=1);
namespace mirzaev\calculator\models\filters;
use mirzaev\calculator\models\filters\import_filter as filter;
use mirzaev\calculator\models\metals_model as metals;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
/**
* Фильтр импорта для документов от "МЕТАЛЛСЕРВИС"
*
* @package mirzaev\calculator\models\filters
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
*/
class import_filter_mc implements filter
{
/**
* Название металла
*/
public string $metal = '';
/**
* Чтение ячейки
*
* @param [type] $columnAddress
* @param [type] $row
* @param string $worksheetName
*
* @return void
*/
public function readCell($columnAddress, $row, $worksheetName = '')
{
return false;
}
/**
* Фильтрация и запись прочитанных данных из EXCEL-документа
*
* @param int $supply Идентификатор поставки (для записи в БД)
* @param Worksheet $spreadsheet Таблица с прочитанными данными
* @param array &$errors Журнал ошибок
*
* @return int Количество записанных строк
*/
public function write(int $supply, Worksheet $spreadsheet, array &$errors = []): int
{
// Инициализация счётчика записанных данных
$writed = 0;
for ($row = 1; $row <= $spreadsheet->getHighestRow(); ++$row) {
// Перебор строк
// Инициализация переменных
$width = $height = $length = $piece = $ton = null;
for ($col = 'A'; $col <= $spreadsheet->getHighestColumn(); ++$col) {
// Перебор столбцов
if ($col === 'B') {
// Колонка с размером
// Чтение из ячейки
$size = $spreadsheet->getCell($col . $row)->getValue();
} else if ($col === 'C') {
// Колонка с маркой
// Чтение из ячейки
$mark = $spreadsheet->getCell($col . $row)->getValue();
} else if ($col === 'E') {
// Колонка с ценой за тонну
// Чтение из ячейки
$ton = (int) round((float) $spreadsheet->getCell($col . $row)->getCalculatedValue());
} else if ($col === 'I') {
// Колонка с ценой за штуку
// Чтение из ячейки
$piece = (int) round((float) $spreadsheet->getCell($col . $row)->getCalculatedValue());
}
}
// Пропуск пустых строк
if (empty($size) || empty($mark) || empty($ton) || empty($piece)) continue;
// Извлечение размеров
preg_match_all('/[\d,\.]+/', $size, $matches);
// Запись размеров
$length = (float) str_replace(',', '.', str_replace('.', '', (string) $matches[0][0]));
$width = (float) str_replace(',', '.', str_replace('.', '', (string) $matches[0][1]));
$height = (float) str_replace(',', '.', str_replace('.', '', (string) $matches[0][2]));
// Запись металла
metals::write($supply, $this->metal, $mark, $width, $height, $length, $piece, $ton, $errors) ? ++$writed : null;
}
return $writed;
}
}

View File

@ -0,0 +1,111 @@
<?php
declare(strict_types=1);
namespace mirzaev\calculator\models\filters;
use mirzaev\calculator\models\filters\import_filter as filter;
use mirzaev\calculator\models\metals_model as metals;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
/**
* Фильтр импорта для документов от неизвестного поставщика под номером 1
*
* @package mirzaev\calculator\models\filters
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
*/
class import_filter_noname_1 implements filter
{
/**
* Название металла
*/
public string $metal = '';
/**
* Чтение ячейки
*
* @param [type] $columnAddress
* @param [type] $row
* @param string $worksheetName
*
* @return void
*/
public function readCell($columnAddress, $row, $worksheetName = '')
{
return false;
}
/**
* Фильтрация и запись прочитанных данных из EXCEL-документа
*
* @param int $supply Идентификатор поставки (для записи в БД)
* @param Worksheet $spreadsheet Таблица с прочитанными данными
* @param array &$errors Журнал ошибок
*
* @return int Количество записанных строк
*/
public function write(int $supply, Worksheet $spreadsheet, array &$errors = []): int
{
// Инициализация счётчика записанных данных
$writed = 0;
for ($row = 1; $row <= $spreadsheet->getHighestRow(); ++$row) {
// Перебор строк
// Инициализация переменных
$width = $height = $length = $piece = $ton = null;
for ($col = 1; $col <= coordinate::columnIndexFromString($spreadsheet->getHighestColumn()); ++$col) {
// Перебор столбцов
if ($col === 1) {
// Колонка с металлом
// Чтение из ячейки
$metal = $spreadsheet->getCellByColumnAndRow($col, $row)->getValue();
} else if ($col === 14) {
// Колонка с коэффициентом
// Чтение из ячейки
$coefficient = (float) $spreadsheet->getCellByColumnAndRow($col, $row)->getValue();
} else if ($col === 15) {
// Колонка с ценой
// Чтение из ячейки
$piece = (int) $spreadsheet->getCellByColumnAndRow($col, $row)->getValue();
}
}
// Пропуск пустых строк
if (empty($metal)) continue;
// Извлечение размеров
preg_match_all('/[\sxх]([\d]+[,\.]?[\d]?)/', $metal, $matches);
// Запись размеров
$length = (float) str_replace(',', '.', str_replace('.', '', (string) $matches[1][0]));
$width = (float) str_replace(',', '.', str_replace('.', '', (string) $matches[1][1]));
$height = (float) str_replace(',', '.', str_replace('.', '', (string) $matches[1][2]));
// Извлечение марки металла
preg_match_all('/\d+\s+(.*)$/', $metal, $matches);
// Запись марки металла
$mark = trim((string) $matches[1][0]);
if ($length > 0 && $width > 0 && $height > 0 && !empty($mark) && $piece > 0 && $coefficient > 0) {
// Найдены все размеры, марка, цена и коэффициент
// Цена за тонну
$ton = (int) round((float) ($piece / $coefficient * 1000));
// Запись металла
metals::write($supply, $this->metal, $mark, $width, $height, $length, $piece, $ton, $errors) ? ++$writed : null;
}
}
return $writed;
}
}

View File

@ -0,0 +1,35 @@
<?php
declare(strict_types=1);
namespace mirzaev\calculator\models\filters;
use mirzaev\calculator\models\filters\import_filter_noname_1;
/**
* Фильтр импорта цен на оцинкованную сталь от "МЕТАЛЛСЕРВИС"
*
* @package mirzaev\calculator\models\filters
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
*
* @todo 1. Доделать 982 до 992 строки
* 2. Доделать 1069 до 1077 строки
*/
final class import_galvanized_steel_filter extends import_filter_mc
{
/**
* Название металла
*/
public string $metal = 'galvanized_steel';
public function readCell($columnAddress, $row, $worksheetName = '')
{
if ($row >= 398 && $row <= 404) {
// Найдены строки с данными (Лист оцинкованный ГОСТ 14918-80)
return true;
}
return false;
}
}

View File

@ -0,0 +1,71 @@
<?php
declare(strict_types=1);
namespace mirzaev\calculator\models\filters;
use mirzaev\calculator\models\filters\import_filter_noname_1;
/**
* Фильтр импорта цен на нержавеющую сталь от неизвестного поставщика под номером 1
*
* @package mirzaev\calculator\models\filters
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
*
* @todo 1. Доделать 982 до 992 строки
* 2. Доделать 1069 до 1077 строки
*/
final class import_stainless_steel_filter extends import_filter_noname_1
{
/**
* Название металла
*/
public string $metal = 'stainless_steel';
public function readCell($columnAddress, $row, $worksheetName = '')
{
if ($row >= 958 && $row <= 982) {
// Найдены строки с маркой 12Х18Н10Т AISI 321
return true;
}
if ($row >= 994 && $row <= 1000) {
// Найдены строки с маркой 08Х17 AISI 430 BA
return true;
}
if ($row >= 1003 && $row <= 1005) {
// Найдены строки с маркой 08Х18Н10 AISI 304 BA+PVC
return true;
}
if ($row >= 1011 && $row <= 1022) {
// Найдены строки с маркой 08Х17 AISI 430 2B
return true;
}
if ($row >= 1024 && $row <= 1069) {
// Найдены строки с маркой 08Х18Н10 AISI 304
return true;
}
if ($row >= 1079 && $row <= 1090) {
// Найдены строки с маркой 08Х17 AISI430 4N+PE
return true;
}
if ($row >= 1092 && $row <= 1099) {
// Найдены строки с маркой 08Х18Н10 AISI 304 4N+PE
return true;
}
return false;
}
}

View File

@ -0,0 +1,56 @@
<?php
declare(strict_types=1);
namespace mirzaev\calculator\models\filters;
use mirzaev\calculator\models\filters\import_filter_mc;
/**
* Фильтр импорта цен на чёрную сталь от "МЕТАЛЛСЕРВИС"
*
* @package mirzaev\calculator\models\filters
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
*/
final class import_steel_filter extends import_filter_mc
{
/**
* Название металла
*/
public string $metal = 'steel';
public function readCell($columnAddress, $row, $worksheetName = '')
{
if ($row >= 305 && $row <= 313) {
// Найдены строки с данными (Лист холоднокатаный ГОСТ 16523-97)
return true;
}
if ($row >= 317 && $row <= 345) {
// Найдены строки с данными (Лист горячекатаный ГОСТ 16523-97; ГОСТ 14637-89)
return true;
}
if ($row >= 349 && $row <= 358) {
// Найдены строки с данными (Лист горячекатаный низколегированный ГОСТ 19281-89)
return true;
}
if ($row >= 385 && $row <= 389) {
// Найдены строки с данными (Лист рифленый ГОСТ 8568-77)
return true;
}
if ($row >= 393 && $row <= 394) {
// Найдены строки с данными (Лист просечно-вытяжной ТУ 36.26.11-5-89)
return true;
}
return false;
}
}

View File

@ -0,0 +1,232 @@
<?php
declare(strict_types=1);
namespace mirzaev\calculator\models;
use mirzaev\calculator\models\settings_model as settings;
use mirzaev\calculator\models\accounts_model as accounts;
use pdo;
use exception;
/**
* Модель металла
*
* @package mirzaev\calculator\models
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
*/
final class metals_model extends core
{
/**
* Расчёт скорость реза металла
*
* @param string $metal Металл
* @param string $gas Газ
* @param float $lenght Толщина
* @param array &$errors Журнал ошибок
*
* @return float|int Скорость реза (мм/с)
*/
public static function cut(string $metal, string $gas, float $lenght, array &$errors = []): float|int
{
try {
return (float) settings::read("cut_speed_${metal}_${gas}_$lenght", $errors) ?? throw new exception('Не удалось определить скорость реза металла');
} catch (exception $e) {
// Запись в журнал ошибок
$errors[] = [
'text' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'stack' => $e->getTrace()
];
}
return 0;
}
/**
* Определение веса
*
* @param string $type Тип
* @param array &$errors Журнал ошибок
*
* @return float|null Вес (кг)
*/
public static function kg(string $type = 'stainless_steel', array &$errors = []): ?float
{
try {
return (float) match ($type) {
'steel' => 8,
'galvanized_steel' => 8,
'stainless_steel' => 8.7,
'brass' => 8.7,
'copper' => 9,
'aluminum' => 3,
default => throw new exception('Не удалось определить тип металла')
};
} catch (exception $e) {
// Запись в журнал ошибок
$errors[] = [
'text' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'stack' => $e->getTrace()
];
}
return null;
}
/**
* Запись в базу данных
*
* @param int $supply Идентификатор записи поставки в базе данных
* @param string $type Тип
* @param string $mark Марка
* @param float $width Ширина (мм)
* @param float $height Высота (мм)
* @param float $length Толщина (мм)
* @param int $piece Цена за лист (руб)
* @param int $ton Цена за тонну (руб)
* @param array &$errors Журнал ошибок
*
* @return bool Статус записи
*/
public static function write(int $supply, string $type, string $mark, float $width, float $height, float $length, int $piece, int $ton, array &$errors = []): bool
{
try {
if ($account = accounts::account($errors)) {
// Инициализирован аккаунт
// Инициализация запроса
$request = static::$db->prepare("INSERT INTO `metals` (`supply`, `type`, `mark`, `width`, `height`, `length`, `piece`, `ton`, `account`) VALUES (:supply, :type, :mark, :width, :height, :length, :piece, :ton, :account)");
// Инициализация параметров
$params = [
':supply' => $supply,
':type' => $type,
':mark' => $mark,
':width' => $width,
':height' => $height,
':length' => $length,
':piece' => $piece,
':ton' => $ton,
':account' => $account['id'],
];
// Отправка запроса
$request->execute($params);
// Получение ответа
return $request->fetch(pdo::FETCH_ASSOC) !== false;
}
} catch (exception $e) {
// Запись в журнал ошибок
$errors[] = [
'text' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'stack' => $e->getTrace()
];
}
return false;
}
/**
* Чтение из базы данных
*
* Очищает от дубликатов
*
* @param string $type Тип
* @param string $mark Марка
* @param float $length Толщина
* @param array &$errors Журнал ошибок
*
* @return float|null Цена за 1 килограмм (руб)
*/
public static function read(string $type, string $mark, float $length, array &$errors = []): ?array
{
try {
// Инициализация запроса
$request = static::$db->prepare("SELECT `width`, `height`, `piece`, `ton` FROM `metals` WHERE `type` = :type && `mark` = :mark && `length` = :length LIMIT 30");
// Отправка запроса
$request->execute([
':type' => $type,
':mark' => $mark,
':length' => $length
]);
// Генерация ответа
$response = $request->fetchAll(pdo::FETCH_ASSOC);
// Проверка на полученные значения
if (!is_array($response)) return false;
if (count($response) === 1) return $response[0];
else if (count($response) > 1) {
// Найдено более чем одно значение
// Инициализация буфера вывода
$buffer = $response[0];
foreach ($response as $metal) {
// Перебор полученных значений металлов
// Запись в буфер металла с самой большей площадью листа
if (($metal['width'] * $metal['height']) > ($buffer['width'] * $buffer['height'])) $buffer = $metal;
}
return $metal;
}
} catch (exception $e) {
// Запись в журнал ошибок
$errors[] = [
'text' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'stack' => $e->getTrace()
];
}
return null;
}
/**
* Поиск и чтение марок металла
*
* Очищает от дубликатов
*
* @param string $type Тип
* @param array &$errors Журнал ошибок
*
* @return float|null Цена за 1 килограмм (руб)
*/
public static function marks(string $type = '*', array &$errors = []): ?array
{
try {
// Инициализация запроса
$request = static::$db->prepare("SELECT DISTINCT `mark` FROM `metals` WHERE `type` = :type");
// Отправка запроса
$request->execute([':type' => $type]);
// Генерация ответа
$response = $request->fetchAll(pdo::FETCH_COLUMN);
return $response === false ? null : (array) $response;
} catch (exception $e) {
// Запись в журнал ошибок
$errors[] = [
'text' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'stack' => $e->getTrace()
];
}
return null;
}
}

View File

@ -16,29 +16,250 @@ use exception;
final class settings_model extends core final class settings_model extends core
{ {
/** /**
* Прочитать * Записать настройку
*
* @param string $name Название параметра
* @param int|float|string|bool $value Значение параметра
* @param array &$errors Журнал ошибок
*
* @return bool Статус записи
*/
public static function write(string $name, int|float|string|bool $value, array &$errors = []): bool
{
try {
// Инициализация запроса
$request = static::$db->prepare("SELECT MAX(`id`) FROM `settings`");
// Отправка запроса
$request->execute();
// Получение ответа
$id = (int) $request->fetchColumn();
// Инициализация запроса
$request = static::$db->prepare("UPDATE `settings` SET `$name` = :value WHERE `id` = $id");
// Параметры запроса
$params = [
":value" => $value
];
// Отправка запроса
$request->execute($params);
// Получение ответа
return $request->fetch(pdo::FETCH_ASSOC) !== false;
} catch (exception $e) {
// Запись в журнал ошибок
$errors[]= [
'text' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'stack' => $e->getTrace()
];
}
return false;
}
/**
* Прочитать настройку
* *
* @param string $name Название параметра * @param string $name Название параметра
* @param array &$errors Журнал ошибок * @param array &$errors Журнал ошибок
* *
* @return array Аккаунт, если найден * @return int|float|string|array|null Значение параметра
*/ */
public static function read(string $name, array &$errors = []): int|float|string|array|null public static function read(string $name = '*', array &$errors = []): int|float|string|array|null
{ {
try { try {
// Инициализация запроса // Инициализация запроса
$request = static::$db->prepare("SELECT `$name` FROM `settings` WHERE `id` = 1 ORDER BY `id` DESC LIMIT 1"); $request = static::$db->prepare("SELECT $name FROM `settings` WHERE `id` = (SELECT MAX(`id`) FROM `settings`) ORDER BY `id` DESC LIMIT 1");
// Отправка запроса // Отправка запроса
$request->execute(); $request->execute();
// Генерация ответа // Генерация ответа
return $request->fetchColumn(); $response = $name === '*' ? $request->fetch(pdo::FETCH_ASSOC) : $request->fetchColumn();
return $response === false ? null : $response;
} catch (exception $e) { } catch (exception $e) {
// Запись в журнал ошибок // Запись в журнал ошибок
$errors[] = $e->getMessage(); $errors[] = [
'text' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'stack' => $e->getTrace()
];
} }
return null; return null;
} }
/**
* Прочитать названия настроек
*
* @param int $limit Максимальное ограничение
* @param array &$errors Журнал ошибок
*
* @return array|null Значение параметра
*/
public static function names(int $limit = 5000, array &$errors = []): ?array
{
try {
// Инициализация запроса
$request = static::$db->prepare("SELECT TABLE_NAME AS 'settings' FROM INFORMATION_SCHEMA.COLUMNS WHERE `table_name` = 'settings'");
// Отправка запроса
$request->execute();
// Генерация ответа
$response = $request->fetchColumn();
return $response === false ? null : (array) $response;
} catch (exception $e) {
// Запись в журнал ошибок
$errors[]= [
'text' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'stack' => $e->getTrace()
];
}
return null;
}
/**
* Фильтровать настройки
*
* Удаляет из массива ненужные данные (id, create...)
*
* @param array $settings Настройки
* @param array &$errors Журнал ошибок
*
* @return array Настройки
*/
public static function filter(array $settings, array &$errors = []): array
{
try {
// Инициализация буфера вывода
$buffer = [];
foreach ($settings as $setting => $value) {
// Перебор настроек
if ($setting === 'id') continue;
if ($setting === 'create') continue;
$buffer[$setting] = $value;
}
return $buffer ?? $settings;
} catch (exception $e) {
// Запись в журнал ошибок
$errors[]= [
'text' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'stack' => $e->getTrace()
];
}
return $settings;
}
/**
* Перевести настройки на русский язык
*
* @param array $settings Настройки
* @param array &$errors Журнал ошибок
*
* @return array Настройки
*/
public static function translate(array $settings, array &$errors = []): array
{
try {
// Инициализация буфера вывода
$buffer = [];
foreach ($settings as $setting => $value) {
// Перебор настроек
$buffer[] = [
'russian' => match ($setting) {
'default_buyer' => 'Покупатель по умолч.',
'default_complexity' => 'Сложность по умолч.',
'default_width' => 'Ширина по умолч. (мм)',
'default_height' => 'Высота по умолч. (мм)',
'default_length' => 'Толщина по умолч. (мм)',
'default_amount' => 'Количество по умолч. (шт)',
'default_type' => 'Тип металла по умолч.',
'default_holes' => 'Отверстия по умол. (шт)',
'default_diameter' => 'Диаметр отверстий по умол. (мм)',
'electricity' => 'Стоимость 1квт',
'laser_power' => 'Потребление лазер. станка (квт)',
'manager_individual_min' => 'Менеджер для физ. лица мин. (ч)',
'manager_individual_max' => 'Менеджер для физ. лица макс. (ч)',
'manager_entity_min' => 'Менеджер для юр. лица мин. (ч)',
'manager_entity_max' => 'Менеджер для юр. лица макс. (ч)',
'manager_entity_hour' => 'Менеджер для юр. лица (руб/час)',
'manager_individual_hour' => 'Менеджер для физ. лица (руб/час)',
'engineer_entity_min' => 'Инженер для юр. лица мин. (ч)',
'engineer_entity_max' => 'Инженер для юр. лица макс. (ч)',
'engineer_entity_hour' => 'Инженер для юр. лица (руб/час)',
'engineer_individual_min' => 'Инженер для физ. лица мин. (ч)',
'engineer_individual_max' => 'Инженер для физ. лица макс. (ч)',
'engineer_individual_hour' => 'Инженер для физ. лица (руб/час)',
'operator_entity_min' => 'Оператор для юр. лица мин. (ч)',
'operator_entity_max' => 'Оператор для юр. лица макс. (ч)',
'operator_individual_min' => 'Оператор для физ. лица мин. (ч)',
'operator_individual_max' => 'Оператор для физ. лица макс. (ч)',
'operator_entity_hour' => 'Оператор для юр. лица (руб/час)',
'operator_individual_hour' => 'Оператор для физ. лица (руб/час)',
'coefficient_area_less' => 'Штраф если пл. меньше (мм)',
'coefficient_area_more' => 'Штраф если пл. больше (мм)',
'coefficient_area_degree' => 'Коэфф. для штрафа по площади',
'coefficient_complexity_easy' => 'Коэфф. низкой слож.',
'coefficient_complexity_medium' => 'Коэфф. средней слож.',
'coefficient_complexity_hard' => 'Коэфф. высокой слож.',
'list_width' => 'Ширина листа (мм)',
'list_height' => 'Высота листа (мм)',
'metal_cost_easy_1_3' => 'Тонна 1-3мм низкая слож. (руб)',
'metal_cost_medium_1_3' => 'Тонна 1-3мм средняя слож. (руб)',
'metal_cost_hard_1_3' => 'Тонна 1-3мм высокая слож. (руб)',
'metal_cost_easy_4_6' => 'Тонна 4-6мм низкая слож. (руб)',
'metal_cost_medium_4_6' => 'Тонна 4-6мм средняя слож. (руб)',
'metal_cost_hard_4_6' => 'Тонна 4-6мм высокая слож. (руб)',
'metal_cost_easy_7_10' => 'Тонна 7-10мм низкая слож. (руб)',
'metal_cost_medium_7_10' => 'Тонна 7-10мм средняя слож. (руб)',
'metal_cost_hard_7_10' => 'Тонна 7-10мм высокая слож. (руб)',
'metal_cost_easy_10' => 'Тонна >10мм низкая слож. (руб)',
'metal_cost_medium_10' => 'Тонна >10мм средняя слож. (руб)',
'metal_cost_hard_10' => 'Тонна >10мм высокая слож. (руб)',
'additive' => 'Коэфф. наценки',
'handyman_hour' => 'Разнорабочий (руб/ч)',
'handyman_metal_load_time' => 'Время установки металла (мин)',
'laser_handymans_amount' => 'Разнорабочие для лазерного станка',
default => $setting
},
'english' => $setting,
'value' => $value
];
}
return $buffer ?? $settings;
} catch (exception $e) {
// Запись в журнал ошибок
$errors[]= [
'text' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'stack' => $e->getTrace()
];
}
return $settings;
}
} }

View File

@ -0,0 +1,82 @@
<?php
declare(strict_types=1);
namespace mirzaev\calculator\models;
use mirzaev\calculator\models\accounts_model as accounts;
use mirzaev\calculator\models\filters\import_filter as filter;
use PhpOffice\PhpSpreadsheet\Reader\Xls as reader;
use pdo;
use exception;
/**
* Модель поставки
*
* @package mirzaev\calculator\models
* @author Arsen Mirzaev Tatyano-Muradovich <arsen@mirzaev.sexy>
*/
final class supplies_model extends core
{
/**
* Запись в базу данных
*
* @param string $file Путь до файла
* @param filter|null $filter Фильтр строк
* @param array &$errors Журнал ошибок
*
* @return bool Статус записи
*/
public static function write(string $file, ?filter $filter = null, array &$errors = []): bool
{
try {
if (file_exists($file) && $account = accounts::account($errors)) {
// Найден файл и инициализирован аккаунт
// Инициализация обработчика документа
$reader = new reader();
// Инициализация фильтра строк
if (isset($filter)) $reader->setReadFilter($filter);
// Чтение файла
$spreadsheet = $reader->load($file)->getActiveSheet();
// Инициализация запроса
$request = static::$db->prepare("INSERT INTO `supplies` (`account`) VALUES (:account)");
// Инициализация параметров
$params = [
':account' => $account['id'],
];
// Отправка запроса
$request->execute($params);
// Запись идентификатора поставки
$supply = (int) (static::$db->lastInsertId() ?? throw new exception('Не удалось найти идентификатор записанной поставки'));
// Запись в базу данных
$filter->write($supply, $spreadsheet, $errors);
return true;
} else {
// Не найден файл
throw new exception("Файл не найден: $file");
}
} catch (exception $e) {
// Запись в журнал ошибок
$errors[] = [
'text' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'stack' => $e->getTrace()
];
}
return false;
}
}

View File

@ -46,15 +46,15 @@
#authentication>form>input[type=submit].registration { #authentication>form>input[type=submit].registration {
padding: 7px 20px; padding: 7px 20px;
background-color: #86781C; background-color: #57bb3b;
} }
#authentication>form>input[type=submit].registration:hover { #authentication>form>input[type=submit].registration:hover {
background-color: #9e8d20; background-color: #59ca3a;
} }
#authentication>form>input[type=submit].registration:is(:active, :focus) { #authentication>form>input[type=submit].registration:is(:active, :focus) {
background-color: #776b19; background-color: #52a93a;
} }
#authentication>form>ul.errors { #authentication>form>ul.errors {

View File

@ -32,54 +32,12 @@
margin: 8px auto 15px; margin: 8px auto 15px;
} }
#calculator>#result>div { #calculator>#result>a#calculate {
width: 30%;
}
#calculator>#result>nav {
margin-right: 30px;
width: 100%;
display: flex;
}
#calculator>#result>nav>a {
margin-top: auto;
}
#calculator>#result>nav>a#calculate {
padding: 10px 5px; padding: 10px 5px;
} }
#calculator>#result,
#calculator>#result>div>p {
font-weight: bold;
display: flex;
}
#calculator>#result>div>p * {
font-weight: normal;
}
#calculator>#result>div,
#calculator>#result>div>p>:is(#expenses, #income, #profit) {
margin-left: auto;
}
#calculator>#result>nav>a:first-child:not(:only-of-type),
#calculator>#result>div>p:first-child:not(:only-of-type) {
margin-top: 0;
}
#calculator>#result>nav>a:last-child,
#calculator>#result>div>p:last-child {
margin-bottom: 0;
}
#calculator>#result>div>p>:last-child {
margin-left: 4px;
}
#calculator>.divider+h3 { #calculator>.divider+h3 {
margin-top: 30px; margin-top: 25px;
} }
#calculator>.calculator { #calculator>.calculator {
@ -119,14 +77,13 @@
} }
#calculator>.calculator>div>div>input { #calculator>.calculator>div>div>input {
width: 25px; width: 50px;
padding: 5px 10px; padding: 5px 8px;
text-align: center; text-align: center;
} }
#calculator>.calculator>div>div>input.measured { #calculator>.calculator>div>div>input.measured {
padding-right: 3px; padding-right: 3px;
text-align: right;
} }
#calculator>.calculator>div>div>small { #calculator>.calculator>div>div>small {
@ -142,3 +99,20 @@
flex-direction: column; flex-direction: column;
justify-content: center; justify-content: center;
} }
#calculator>.calculator>div>div,
#calculator>.calculator>div>div>select {
max-width: 100%;
}
#calculator>.calculator>div>div>input:is([type="checkbox"], [type="radio"]) {
width: min-content;
height: 1rem;
margin: auto 0;
padding: 0;
display: unset;
}
#calculator>.calculator>div>div>input[type="range"] {
min-width: 50%;
}

View File

@ -27,6 +27,7 @@ aside>section>h3 {
} }
:is(main, aside) { :is(main, aside) {
min-height: calc(100vh - calc(16px + 40px) - 150px - 30px - 30px);
margin-top: 30px; margin-top: 30px;
display: inline-block; display: inline-block;
grid-row: 2; grid-row: 2;
@ -45,6 +46,10 @@ main {
grid-column: 3; grid-column: 3;
} }
main>section {
min-height: 25vh;
}
main>section>h2 { main>section>h2 {
margin-left: 1.5rem; margin-left: 1.5rem;
margin-top: unset; margin-top: unset;
@ -56,7 +61,6 @@ main>section>h2+.divider {
margin-top: -1rem; margin-top: -1rem;
} }
header { header {
z-index: 1000; z-index: 1000;
width: 100%; width: 100%;
@ -91,6 +95,11 @@ header>nav *:hover,
header>nav>#logo>img:hover::before { header>nav>#logo>img:hover::before {
color: #fff; color: #fff;
} }
header>nav *:is(:active, :focus),
header>nav>#logo>img:is(:active, :focus)::before {
outline: none;
border: none;
}
header>nav>#logo>img { header>nav>#logo>img {
height: inherit; height: inherit;
@ -161,6 +170,7 @@ input[type="submit"]:hover {
input[type="radio"]:checked+label[type="button"], input[type="radio"]:checked+label[type="button"],
input[type="submit"]:is(:active, :focus) { input[type="submit"]:is(:active, :focus) {
color: #ddd; color: #ddd;
outline: none;
background-color: #aa4646; background-color: #aa4646;
} }
@ -169,14 +179,22 @@ input:is([type="checkbox"], [type="radio"]) {
} }
select, select,
input:is([type="text"], [type="password"]), input:is([type="text"], [type="number"], [type="range"], [type="password"]),
input:is([type="text"], [type="password"]).measured + .unit { input:is([type="text"], [type="number"], [type="range"], [type="password"]).measured + .unit {
padding: 8px 12px; padding: 8px 12px;
outline: unset; outline: unset;
border-radius: 3px; border-radius: 3px;
border: unset; border: unset;
} }
input[type="range"] {
cursor: grab;
}
input[type="range"]:active {
cursor: grabbing;
}
select { select {
padding-top: unset; padding-top: unset;
padding-bottom: unset; padding-bottom: unset;
@ -187,7 +205,7 @@ select {
} }
select.measured, select.measured,
input:is([type="text"], [type="password"]).measured { input:is([type="text"], [type="number"], [type="range"], [type="password"]).measured {
margin-right: unset; margin-right: unset;
padding-right: 3px; padding-right: 3px;
text-align: right; text-align: right;
@ -195,7 +213,7 @@ input:is([type="text"], [type="password"]).measured {
} }
select.measured + .unit, select.measured + .unit,
input:is([type="text"], [type="password"]).measured + .unit { input:is([type="text"], [type="number"], [type="range"], [type="password"]).measured + .unit {
margin-right: 3px; margin-right: 3px;
padding-left: unset; padding-left: unset;
display: inline; display: inline;

View File

@ -0,0 +1,23 @@
#settings>.setting {
margin-bottom: 15px;
display: flex;
align-items: center;
}
#settings>.setting:last-child {
margin-bottom: 0;
}
#settings>.setting>label {
margin-left: auto;
margin-right: 10px;
}
#settings>.setting>input {
width: 20%;
margin-right: 15%;
padding: 6px 10px;
}
#settings>h2.supplies {
margin-top: 40px;
}

View File

@ -7,6 +7,7 @@ namespace mirzaev\calculator;
use mirzaev\minimal\core; use mirzaev\minimal\core;
use mirzaev\minimal\router; use mirzaev\minimal\router;
define('SUPPLIES', realpath('supplies'));
define('VIEWS', realpath('..' . DIRECTORY_SEPARATOR . 'views')); define('VIEWS', realpath('..' . DIRECTORY_SEPARATOR . 'views'));
define('TYPE', 'mysql'); define('TYPE', 'mysql');
define('BASE', 'calculator'); define('BASE', 'calculator');
@ -32,12 +33,16 @@ $router->write('/calculator/generate/buyer', 'calculator', 'buyer', 'POST');
$router->write('/calculator/generate/complexity', 'calculator', 'complexity', 'POST'); $router->write('/calculator/generate/complexity', 'calculator', 'complexity', 'POST');
$router->write('/calculator/generate/menu', 'calculator', 'menu', 'POST'); $router->write('/calculator/generate/menu', 'calculator', 'menu', 'POST');
$router->write('/calculator/generate/result', 'calculator', 'result', 'POST'); $router->write('/calculator/generate/result', 'calculator', 'result', 'POST');
$router->write('/calculator/generate/mark', 'calculator', 'mark', 'POST');
$router->write('/calculator/generate/divider', 'calculator', 'divider', 'POST'); $router->write('/calculator/generate/divider', 'calculator', 'divider', 'POST');
$router->write('/calculator/generate/laser', 'calculator', 'laser', 'POST'); $router->write('/calculator/generate/laser', 'calculator', 'laser', 'POST');
$router->write('/calculator/calculate', 'calculator', 'calculate', 'POST'); $router->write('/calculator/calculate', 'calculator', 'calculate', 'POST');
$router->write('/settings', 'settings', 'index', 'GET'); $router->write('/settings', 'settings', 'index', 'GET');
$router->write('/settings/write', 'settings', 'write', 'POST'); $router->write('/settings/write', 'settings', 'write', 'POST');
$router->write('/settings/read', 'settings', 'read', 'POST'); $router->write('/settings/read', 'settings', 'read', 'POST');
$router->write('/supplies/write', 'supplies', 'write', 'POST');
$router->write('/journal', 'journal', 'index', 'GET');
$router->write('/contacts', 'contacts', 'index', 'GET');
// Инициализация ядра // Инициализация ядра
$core = new Core(namespace: __NAMESPACE__, router: $router); $core = new Core(namespace: __NAMESPACE__, router: $router);

View File

@ -13,29 +13,37 @@ let calculator = {
init() { init() {
// Инициализация калькулятора // Инициализация калькулятора
// !!!!!!!!!!!!!!!!! РАЗОБРАТЬСЯ С ПОРЯДКОМ ВЫПОЛНЕНИЯ
this.generate.buyer(this.settings.defaults.buyer) this.generate.buyer(this.settings.defaults.buyer)
.then(this.generate.complexity(this.settings.defaults.complexity) .then(
.then(this.generate.menu() success => {
.then(this.authenticate(cookie.read('id')) this.generate.complexity(this.settings.defaults.complexity)
.then(success => { .then(
// Запись данных аккаунта success => {
this.account = success; this.generate.menu()
.then(
success => {
this.authenticate(cookie.read('id'))
.then(
success => {
// Запись данных аккаунта
this.account = success;
if (this.account !== undefined && typeof this.account === 'object' && this.account.permissions !== undefined) { if (this.account !== undefined && typeof this.account === 'object' && this.account.permissions !== undefined) {
// Найден аккаунт // Найден аккаунт
if (this.account.permissions.calculate == 1) { if (this.account.permissions.calculate == 1) {
// Разрешено использовать калькулятор // Разрешено использовать калькулятор
this.generate.result(); this.generate.result();
} }
}
}
);
}
);
} }
} );
) }
)
)
); );
console.log('[КАЛЬКУЛЯТОР] Инициализирован'); console.log('[КАЛЬКУЛЯТОР] Инициализирован');
@ -63,9 +71,6 @@ let calculator = {
calculate() { calculate() {
// Запрос и генерация HTML с данными о рассчете со всех калькуляторов // Запрос и генерация HTML с данными о рассчете со всех калькуляторов
// Инициализация буферов вывода
let expenses, income, profit;
// Инициализация буфера запроса // Инициализация буфера запроса
let query = {}; let query = {};
@ -76,7 +81,7 @@ let calculator = {
query[number] = {}; query[number] = {};
// Инициализация типа калькулятора // Инициализация типа калькулятора
query[number]['type'] = this.calculators[number].getAttribute('data-calculator'); query[number]['calculator'] = this.calculators[number].getAttribute('data-calculator');
for (const buyer of this.index.querySelectorAll('input[name="buyer"]')) { for (const buyer of this.index.querySelectorAll('input[name="buyer"]')) {
// Перебор полей с параметрами типа заказчика // Перебор полей с параметрами типа заказчика
@ -103,40 +108,97 @@ let calculator = {
for (const field of this.calculators[number].querySelectorAll('[data-calculator-parameter]')) { for (const field of this.calculators[number].querySelectorAll('[data-calculator-parameter]')) {
// Перебор полей с параметрами // Перебор полей с параметрами
// Запись в буфер запроса if (field.getAttribute('type') === 'checkbox') {
query[number][field.getAttribute('data-calculator-parameter')] = field.value ?? field.options[field.selectedIndex].text; // Флажок
// Запись в буфер запроса
query[number][field.getAttribute('data-calculator-parameter')] = field.checked;
} else if (field.getAttribute('type') === 'text' || field.getAttribute('type') === 'number' || field.getAttribute('type') === 'range') {
// Текстовое, цифровое поле или ползунок
// Запись в буфер запроса
query[number][field.getAttribute('data-calculator-parameter')] = field.value;
} else {
// Элемент с тегом <select> (подразумевается)
// Запись в буфер запроса
query[number][field.getAttribute('data-calculator-parameter')] = field.value ?? field.options[field.selectedIndex].text;
}
} }
// Сортировка // Сортировка
query[number] = this.sort[query[number]['type']](query[number]); query[number] = query[number];
} }
fetch('/calculator/calculate', { return fetch('/calculator/calculate', {
method: "POST", method: "POST",
headers: { "content-type": "application/json" }, headers: { "content-type": "application/json" },
body: JSON.stringify(query) body: JSON.stringify(query)
}).then((response) => { }).then((response) => {
if (response.status === 200) { if (response.status === 200) {
return response.json().then( response.json().then(
success => { success => {
console.log('[КАЛЬКУЛЯТОР] Сгенерирован результат'); // Инициализация буфера расходов
let expenses = 0;
return success; for (const [, machine] of Object.entries(success.machines)) {
// Перебор станков
// Прибавление данных к буферу расходов
expenses += (machine.electricity + (machine.metal ?? 0));
}
for (const [, manager] of Object.entries(success.managers)) {
// Перебор менеджеров
// Прибавление данных к буферу расходов
expenses += manager.time * manager.hour;
}
for (const [, engineer] of Object.entries(success.engineers)) {
// Перебор менеджеров
// Прибавление данных к буферу расходов
expenses += engineer.time * engineer.hour;
}
for (const [, operator] of Object.entries(success.operators)) {
// Перебор операторов
// Прибавление данных к буферу расходов
expenses += (operator.time.design + operator.time.machine) * operator.hour;
}
for (const [, handyman] of Object.entries(success.handymans)) {
// Перебор разнорабочих
// Прибавление данных к буферу расходов
expenses += handyman.time * handyman.hour;
}
// Добавление переработки
expenses += success.other.reprocessing;
// Добавление наценки (коэффициент)
expenses *= success.other.additive;
// Добавление скидки менеджера
expenses -= expenses * (success.other.discount / 100)
// Округление
expenses = expenses.toFixed(2);
if (this.generate.result(expenses + ' рублей')) {
console.log(`[КАЛЬКУЛЯТОР] Сгенерирован результат: ${expenses} рублей`);
} else {
console.log('[КАЛЬКУЛЯТОР] [ОШИБКА] Не удалось сгенерировать результат');
}
}, },
error => { error => {
console.log('[КАЛЬКУЛЯТОР] [ОШИБКА] Не удалось сгенерировать результат'); console.log('[КАЛЬКУЛЯТОР] [ОШИБКА] Не удалось сгенерировать результат');
}); });
} }
}); });
let result = document.getElementById("result");
if (result === null) {
// Не найден элемент с данными рассчета
// Инициализия
this.generate.result();
}
}, },
generate: { generate: {
buyer(value = 'individual') { buyer(value = 'individual') {
@ -199,22 +261,84 @@ let calculator = {
} }
}); });
}, },
result() { result(expenses) {
// Запрос и генерация HTML с данными о результате калькуляции // Запрос и генерация HTML с данными о результате калькуляции
return fetch('/calculator/generate/result', { function request() {
return fetch('/calculator/generate/result', {
method: "POST",
headers: { "content-type": "application/x-www-form-urlencoded" }
}).then((response) => {
if (response.status === 200) {
response.text().then(
success => {
calculator.index.insertAdjacentHTML('beforeend', success);
console.log('[КАЛЬКУЛЯТОР] Загружен элемент с данными о результате калькуляции');
},
error => {
console.log('[КАЛЬКУЛЯТОР] [ОШИБКА] Не удалось загрузить элемент с данными о результате калькуляции');
});
}
});
}
if (document.getElementById("result") === null) {
// Не найден элемент с данными расчётов
// Генерация элемента с данными расчётов
}
if (expenses !== undefined) {
// Переданы расходы
// Инициализация элемента
let element = document.getElementById('calculate');
if (element == null) {
// Не найден элемент с результатом расчёта
return false;
}
// Запись расходов в элемент (подразумевается кнопка отправки на расчёт)
element.innerText = expenses;
return true;
}
return request();
},
mark(element, type = '') {
// Запрос и генерация HTML с полем выбора марки металла
return fetch('/calculator/generate/mark?type=' + type, {
method: "POST", method: "POST",
headers: { "content-type": "application/x-www-form-urlencoded" } headers: { "content-type": "application/x-www-form-urlencoded" }
}).then((response) => { }).then((response) => {
if (response.status === 200) { if (response.status === 200) {
response.text().then( response.text().then(
success => { success => {
calculator.index.insertAdjacentHTML('beforeend', success); // Поиск устаревшего списка с марками
let old = element.querySelectorAll('select[name="mark"]')[0];
console.log('[КАЛЬКУЛЯТОР] Загружен элемент с данными о результате калькуляции'); if (old !== undefined) {
// Найден список с марками
// Деинициализация
old.parentElement.parentElement.remove();
}
// Инициализация оболочки в которую необходимо записать список
let wrap = element.querySelectorAll('select[name="type"]')[0].parentElement.parentElement
// Запись полученного списка в оболочку
wrap.insertAdjacentHTML('afterend', success);
console.log('[КАЛЬКУЛЯТОР] Загружен список с марками металла');
}, },
error => { error => {
console.log('[КАЛЬКУЛЯТОР] [ОШИБКА] Не удалось загрузить элемент с данными о результате калькуляции'); console.log('[КАЛЬКУЛЯТОР] [ОШИБКА] Не удалось загрузить список с марками металла');
}); });
} }
}); });
@ -253,7 +377,30 @@ let calculator = {
laser() { laser() {
// Запрос и генерация HTML с калькулятором лазерной резки // Запрос и генерация HTML с калькулятором лазерной резки
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ИЗБАВИТЬСЯ ОТ ТАЙМАУТОВ function write(target, position, html) {
if (target === undefined || position === undefined || html === undefined) return false;
// Запись калькулятора после последнего калькулятора
target.insertAdjacentHTML(position, html);
// Поиск калькуляторов
let calculators = calculator.index.querySelectorAll('section[data-calculator]');
// Инициализация идентификатора калькулятора
let id = calculators.length - 1;
// Запись калькулятору его идентификатора
calculators[id].id = 'laser_' + id;
// Запись в реестр последнего калькулятора (подразумевается, что он новый и только что был записан)
calculator.calculators.push(calculators[id]);
// Запись в журнал
console.log('[КАЛЬКУЛЯТОР] Инициализирован калькулятор лазерной резки');
// Инициализация поля с маркой металла
calculator.generate.mark(calculators[id]);
}
return fetch('/calculator/generate/laser', { return fetch('/calculator/generate/laser', {
method: "POST", method: "POST",
@ -269,92 +416,40 @@ let calculator = {
// Найден калькулятор // Найден калькулятор
// Инициализация разделителя перед меню // Инициализация разделителя перед меню
calculator.generate.divider(last, 'afterend').then( calculator.generate.divider(last, 'afterend').then(divider => write(last, 'afterend', success));
divider => {
// Запись калькулятора после последнего калькулятора
last.insertAdjacentHTML('afterend', success);
// Поиск калькуляторов
let calculators = calculator.index.querySelectorAll('section[data-calculator]');
// Запись в реестр последнего калькулятора (подразумевается, что он новый и только что был записан)
calculator.calculators.push(calculators[calculators.length - 1]);
// Запись в журнал
console.log('[КАЛЬКУЛЯТОР] Инициализирован калькулятор лазерной резки');
}
);
} else { } else {
// Не найден калькулятор // Не найден калькулятор
// Поиск меню calculator.generate.divider(menu, 'beforebegin').then(
let menu = document.getElementById("menu"); first => {
// Поиск меню
let menu = document.getElementById("menu");
if (menu !== null) { if (menu !== null) {
// Найдено меню // Найдено меню
// Инициализация разделителя перед меню // Инициализация разделителя перед меню
calculator.generate.divider(menu, 'beforebegin').then( calculator.generate.divider(menu, 'beforebegin').then(divider => write(menu, 'beforebegin', success));
divider => { } else {
// Запись калькулятора перед меню // Не найдено меню
menu.insertAdjacentHTML('beforebegin', success);
// Поиск калькуляторов // Поиск результатов калькуляции
let calculators = calculator.index.querySelectorAll('section[data-calculator]'); let result = document.getElementById("result");
// Запись в реестр последнего калькулятора (подразумевается, что он новый и только что был записан) if (result !== null) {
calculator.calculators.push(calculators[calculators.length - 1]); // Найден элемент с результатами калькуляции
// Запись в журнал // Инициализация разделителя перед меню
console.log('[КАЛЬКУЛЯТОР] Инициализирован калькулятор лазерной резки'); calculator.generate.divider(result, 'beforebegin').then(result => write(result, 'beforebegin', success));
} else {
// Не найден элемент с результатами калькуляции
// Инициализация разделителя перед меню
calculator.generate.divider().then(result => write(calculator.index, 'beforeend', success));
}
} }
);
} else {
// Не найдено меню
// Поиск результатов калькуляции
let result = document.getElementById("result");
if (result !== null) {
// Найден элемент с результатами калькуляции
// Инициализация разделителя перед меню
calculator.generate.divider(result, 'beforebegin').then(
divider => {
// Запись калькулятора перед элементом с результатами калькуляции
result.insertAdjacentHTML('beforebegin', success);
// Поиск калькуляторов
let calculators = calculator.index.querySelectorAll('section[data-calculator]');
// Запись в реестр последнего калькулятора (подразумевается, что он новый и только что был записан)
calculator.calculators.push(calculators[calculators.length - 1]);
// Запись в журнал
console.log('[КАЛЬКУЛЯТОР] Инициализирован калькулятор лазерной резки');
}
);
} else {
// Не найден элемент с результатами калькуляции
// Инициализация разделителя перед меню
calculator.generate.divider().then(
divider => {
// Запись калькулятора в конце калькулятора
calculator.index.insertAdjacentHTML('beforeend', success);
// Поиск калькуляторов
let calculators = calculator.index.querySelectorAll('section[data-calculator]');
// Запись в реестр последнего калькулятора (подразумевается, что он новый и только что был записан)
calculator.calculators.push(calculators[calculators.length - 1]);
// Запись в журнал
console.log('[КАЛЬКУЛЯТОР] Инициализирован калькулятор лазерной резки');
}
);
} }
} );
} }
}, },
error => { error => {
@ -365,23 +460,5 @@ let calculator = {
}); });
} }
} }
},
sort: {
laser(parameters) {
// Сортировка параметров для отправки на сервер (динамически вызывается функция-обработчик)
return {
type: 'laser',
buyer: parameters['buyer'] ?? null,
complexity: parameters['complexity'] ?? null,
width: parameters['width'] ?? null,
height: parameters['width'] ?? null,
length: parameters['length'] ?? null,
amount: parameters['amount'] ?? null,
metal: parameters['metal'] ?? null,
holes: parameters['holes'] ?? null,
diameter: parameters['diameter'] ?? null,
};
}
} }
}; };

View File

@ -0,0 +1,36 @@
'use strict';
let settings = {
write(input) {
if (input !== undefined && input !== null) {
// Передан элемент
// Инициализация буфера с данными запроса
let body = {};
// Запись в буфер
body[input.name] = input.value;
return fetch('/settings/write', {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify(body)
}).then((response) => {
if (response.status === 200) {
response.text().then(
success => {
console.log('[КАЛЬКУЛЯТОР] Записана настройка: ' + input.name);
// Переоткрытие страницы
// location.reload();
},
error => {
console.log('[КАЛЬКУЛЯТОР] [ОШИБКА] Не удалось записать настройку: ' + input.name);
});
}
});
}
return false;
}
};

View File

@ -0,0 +1,32 @@
'use strict';
let supplies = {
write(file) {
if (file !== undefined && file !== null) {
// Передан файл
// Инициализация буфера с данными запроса
let data = new FormData;
// Запись в буфер
data.append('supplies', file);
return fetch('/supplies/write', {
method: "POST",
body: data
}).then((response) => {
if (response.status === 200) {
response.text().then(
success => {
console.log('[КАЛЬКУЛЯТОР] Загружены данные о поставках металла');
},
error => {
console.log('[КАЛЬКУЛЯТОР] [ОШИБКА] Не удалось загрузить данные о поставках металла');
});
}
});
}
return false;
}
};

View File

@ -0,0 +1,10 @@
<div>
<label>Марка</label>
<div>
<select name="mark" data-calculator-parameter="mark" title="Марка стали">
{% for mark in marks %}
<option value="{{ mark }}">{{ mark }}</option>
{% endfor %}
</select>
</div>
</div>

View File

@ -0,0 +1,92 @@
<h3>Лазерная резка</h3>
<section class="calculator" data-calculator="laser">
<div>
<label>Тип</label>
<div>
<select name="type" data-calculator-parameter="type" title="Тип стали"
onchange="calculator.generate.mark(this.parentElement.parentElement.parentElement, this.value)">
<option value="steel">Сталь</option>
<option value="galvanized_steel">Оцинкованная сталь</option>
<option value="stainless_steel">Нержавеющая сталь</option>
<option value="brass">Латунь</option>
<option value="copper">Медь</option>
<option value="aluminum">Алюминий</option>
</select>
</div>
</div>
<div>
<label>Размер</label>
<div>
<input data-calculator-parameter="width" type="number" class="measured" title="Длина детали"
value="{{ calculators.laser.width }}" min="{{ calculators.laser.width.min ?? 1 }}"
max="{{ calculators.laser.width.max ?? 3000 }}">
<span class="unit unselectable">мм</span>
<small>x</small>
<input data-calculator-parameter="height" type="number" class="measured" title="Ширина детали"
value="{{ calculators.laser.height }}" min="{{ calculators.laser.height.min ?? 1 }}"
max="{{ calculators.laser.height.max ?? 3000 }}">
<span class="unit unselectable">мм</span>
<small>x</small>
<input data-calculator-parameter="length" type="number" class="measured" title="Толщина детали"
value="{{ calculators.laser.length }}" min="{{ calculators.laser.length.min ?? 1 }}"
max="{{ calculators.laser.length.max ?? 20 }}">
<span class="unit unselectable">мм</span>
</div>
</div>
<div>
<label>Отверстия</label>
<div>
<input data-calculator-parameter="holes" type="number" class="measured" title="Количество отверстий"
value="{{ calculators.laser.holes }}" min="{{ calculators.laser.holes.min ?? 0 }}"
max="{{ calculators.laser.holes.max ?? 100 }}">
<span class="unit unselectable">шт</span>
<small>x</small>
<input data-calculator-parameter="diameter" type="number" class="measured" title="Диаметр отверстий"
value="{{ calculators.laser.diameter }}" min="{{ calculators.laser.diameter.min ?? 0 }}"
max="{{ calculators.laser.diameter.max ?? 100 }}">
<span class="unit unselectable">мм</span>
</div>
</div>
<div>
<label>Количество</label>
<div>
<input data-calculator-parameter="amount" type="number" class="measured" title="Количество изделий"
value="{{ calculators.laser.amount }}" min="{{ calculators.laser.amount.min ?? 1 }}"
max="{{ calculators.laser.amount.max ?? 10000 }}">
<span class="unit unselectable">шт</span>
</div>
</div>
<div>
<label for="our">Наш металл</label>
<div>
<input data-calculator-parameter="our" type="checkbox" title="Используется наш металл" checked>
</div>
</div>
<div>
<label>Скидка ({{ calculators.laser.discount.default ?? 0 }}%)</label>
<div>
<input data-calculator-parameter="discount" type="range" title="Скидка менеджера"
value="{{ calculators.laser.discount.default ?? 0 }}" min="{{ calculators.laser.discount.min ?? 0 }}"
max="{{ calculators.laser.discount.max ?? 5 }}" step="{{ calculators.laser.discount.step ?? 1 }}" oninput="this.parentElement.parentElement.children[0].innerText = 'Скидка (' + this.value + '%)';">
<!-- <datalist id="discount_level">
<option value="0" label="{{ calculators.laser.discount.min ?? 0 }}%">
<option value="10">
<option value="20">
<option value="30">
<option value="40">
<option value="50" label="{{ ((calculators.laser.discount.max ?? 5) + (calculators.laser.discount.min ?? 0)) / 2 }}%">
<option value="60">
<option value="70">
<option value="80">
<option value="90">
<option value="100" label="{{ calculators.laser.discount.max ?? 5 }}%">
</datalist> -->
</div>
</div>
</section>

View File

@ -0,0 +1,6 @@
<section id="buyer" class="unselectable">
<input id="individual" type="radio" name="buyer" value="individual" {% if buyer is same as('individual') %}checked{% endif %}>
<label type="button" for="individual">Физическое лицо</label>
<input id="entity" type="radio" name="buyer" value="entity" {% if buyer is same as('entity') %}checked{% endif %}>
<label type="button" for="entity">Юридическое лицо</label>
</section>

View File

@ -1,45 +0,0 @@
<h3>Лазерная резка</h3>
<section class="calculator" data-calculator="laser">
<div>
<label>Металл</label>
<div>
<select name="metal" data-calculator-parameter="metal">
<option value="steel">Сталь</option>
<option value="stainless_steel" selected>Нержавеющая сталь</option>
<option value="brass">Латунь</option>
<option value="copper">Медь</option>
<option value="aluminum">Алюминий</option>
</select>
</div>
</div>
<div>
<label>Размер</label>
<div>
<input data-calculator-parameter="width" type="text" class="measured" title="Длина" value="100">
<span class="unit unselectable">мм</span>
<small>x</small>
<input data-calculator-parameter="height" type="text" class="measured" title="Ширина" value="100">
<span class="unit unselectable">мм</span>
<small>x</small>
<input data-calculator-parameter="length" type="text" class="measured" title="Толщина" value="1">
<span class="unit unselectable">мм</span>
</div>
</div>
<div>
<label>Отверстия</label>
<div>
<input data-calculator-parameter="holes" type="text" class="measured" title="Количество" value="1">
<span class="unit unselectable">шт</span>
<small>x</small>
<input data-calculator-parameter="diameter" type="text" class="measured" title="Диаметр" value="1">
<span class="unit unselectable">мм</span>
</div>
</div>
<div>
<label>Количество</label>
<div>
<input data-calculator-parameter="amount" type="text" class="measured" title="Количество" value="1">
<span class="unit unselectable">шт</span>
</div>
</div>
</section>

View File

@ -1,10 +1,3 @@
<section id="result"> <section id="result">
<nav class="unselectable"> <a id="calculate" class="unselectable" type="button" onclick="return calculator.calculate();">0 рублей</a>
<a id="calculate" type="button" onclick="return calculator.calculate();">Рассчитать</a>
</nav>
<div>
<p class="unselectable">Расходы: <span id="expenses">0</span><span>рублей</span></p>
<p class="unselectable">Доход: <span id="income">0</span><span>рублей</span></p>
<p class="unselectable">Прибыль: <span id="profit">0</span><span>рублей</span></p>
</div>
</section> </section>

View File

@ -0,0 +1,10 @@
{% extends "core.html" %}
{% block main %}
<link href="/css/contacts.css" rel="stylesheet">
<section id="contacts">
<h2>Контакты</h2>
<div class="divider"></div>
</section>
{% endblock %}

View File

@ -20,7 +20,9 @@
<aside> <aside>
{% include 'sidebar.html' %} {% include 'sidebar.html' %}
</aside><!----><main> </aside>
<main>
{% block main %} {% block main %}
{% include 'calculators/index.html' %} {% include 'calculators/index.html' %}
{% endblock %} {% endblock %}

View File

@ -3,12 +3,12 @@
<a id="logo" href="/" title="Калькулятор расходов"> <a id="logo" href="/" title="Калькулятор расходов">
<img src="" alt="Калькулятор"> <img src="" alt="Калькулятор">
</a> </a>
<a class="link" href="/contacts" title="Связь с администрацией">Контакты</a>
<a class="link" href="/journal" title="Записи рассчётов">Журнал</a>
{% if account is not empty %} {% if account is not empty %}
<a class="link" href="/journal" title="Записи рассчётов">Журнал</a>
{% if account.permissions.settings is defined and account.permissions.settings == 1 %} {% if account.permissions.settings is defined and account.permissions.settings == 1 %}
<a class="link" href="/settings" title="Настройки калькуляторов">Настройки</a> <a class="link" href="/settings" title="Настройки калькуляторов">Настройки</a>
{% endif %} {% endif %}
{% endif %} {% endif %}
<a class="link" href="/contacts" title="Связь с администрацией">Контакты</a>
</nav> </nav>
</header> </header>

View File

@ -0,0 +1,10 @@
{% extends "core.html" %}
{% block main %}
<link href="/css/journal.css" rel="stylesheet">
<section id="journal">
<h2>Журнал</h2>
<div class="divider"></div>
</section>
{% endblock %}

View File

@ -0,0 +1,25 @@
{% extends "core.html" %}
{% block main %}
<link href="/css/settings.css" rel="stylesheet">
<section id="settings">
<h2>Настройки</h2>
<div class="divider"></div>
{% for setting in settings %}
<div class="setting">
<label class="unselectable" for="{{ setting.english }}">{{ setting.russian }}</label>
<input id="{{ setting.english }}" type="text" name="{{ setting.english }}" value="{{ setting.value }}" onchange="settings.write(this)">
</div>
{% endfor %}
{% if account.permissions.supplies is defined and account.permissions.supplies == 1 %}
<h2 class="supplies">Поставки</h2>
<div class="divider"></div>
<input type="file" name="supply" onchange="supplies.write(this.files[0])">
{% endif %}
</section>
<script type="text/javascript" src="/js/settings.js" defer></script>
<script type="text/javascript" src="/js/supplies.js" defer></script>
{% endblock %}

View File

@ -25,24 +25,60 @@ class InstalledVersions
private static $installed = array ( private static $installed = array (
'root' => 'root' =>
array ( array (
'pretty_version' => '1.0.0+no-version-set', 'pretty_version' => 'dev-stable',
'version' => '1.0.0.0', 'version' => 'dev-stable',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => NULL, 'reference' => '503e25647cabfd80c98a1ca571a98e4b0595b729',
'name' => 'mirzaev/calculator', 'name' => 'mirzaev/calculator',
), ),
'versions' => 'versions' =>
array ( array (
'mirzaev/calculator' => 'ezyang/htmlpurifier' =>
array ( array (
'pretty_version' => '1.0.0+no-version-set', 'pretty_version' => 'v4.14.0',
'version' => '1.0.0.0', 'version' => '4.14.0.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => NULL, 'reference' => '12ab42bd6e742c70c0a52f7b82477fcd44e64b75',
),
'maennchen/zipstream-php' =>
array (
'pretty_version' => '2.1.0',
'version' => '2.1.0.0',
'aliases' =>
array (
),
'reference' => 'c4c5803cc1f93df3d2448478ef79394a5981cc58',
),
'markbaker/complex' =>
array (
'pretty_version' => '3.0.1',
'version' => '3.0.1.0',
'aliases' =>
array (
),
'reference' => 'ab8bc271e404909db09ff2d5ffa1e538085c0f22',
),
'markbaker/matrix' =>
array (
'pretty_version' => '3.0.0',
'version' => '3.0.0.0',
'aliases' =>
array (
),
'reference' => 'c66aefcafb4f6c269510e9ac46b82619a904c576',
),
'mirzaev/calculator' =>
array (
'pretty_version' => 'dev-stable',
'version' => 'dev-stable',
'aliases' =>
array (
),
'reference' => '503e25647cabfd80c98a1ca571a98e4b0595b729',
), ),
'mirzaev/minimal' => 'mirzaev/minimal' =>
array ( array (
@ -53,6 +89,60 @@ private static $installed = array (
), ),
'reference' => 'b6f90b700116f20fe48725166ddfb8f6d27ae52d', 'reference' => 'b6f90b700116f20fe48725166ddfb8f6d27ae52d',
), ),
'myclabs/php-enum' =>
array (
'pretty_version' => '1.8.3',
'version' => '1.8.3.0',
'aliases' =>
array (
),
'reference' => 'b942d263c641ddb5190929ff840c68f78713e937',
),
'phpoffice/phpspreadsheet' =>
array (
'pretty_version' => '1.20.0',
'version' => '1.20.0.0',
'aliases' =>
array (
),
'reference' => '44436f270bb134b4a94670f3d020a85dfa0a3c02',
),
'psr/http-client' =>
array (
'pretty_version' => '1.0.1',
'version' => '1.0.1.0',
'aliases' =>
array (
),
'reference' => '2dfb5f6c5eff0e91e20e913f8c5452ed95b86621',
),
'psr/http-factory' =>
array (
'pretty_version' => '1.0.1',
'version' => '1.0.1.0',
'aliases' =>
array (
),
'reference' => '12ac7fcd07e5b077433f5f2bee95b3a771bf61be',
),
'psr/http-message' =>
array (
'pretty_version' => '1.0.1',
'version' => '1.0.1.0',
'aliases' =>
array (
),
'reference' => 'f6561bf28d520154e4b0ec72be95418abe6d9363',
),
'psr/simple-cache' =>
array (
'pretty_version' => '1.0.1',
'version' => '1.0.1.0',
'aliases' =>
array (
),
'reference' => '408d5eafb83c57f6365a3ca330ff23aa4a5fa39b',
),
'symfony/polyfill-ctype' => 'symfony/polyfill-ctype' =>
array ( array (
'pretty_version' => 'v1.23.0', 'pretty_version' => 'v1.23.0',

View File

@ -6,6 +6,7 @@ $vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir); $baseDir = dirname($vendorDir);
return array( return array(
'320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php',
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php', '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
'320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php',
'2cffec82183ee1cea088009cef9a6fc3' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier.composer.php',
); );

View File

@ -6,4 +6,5 @@ $vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir); $baseDir = dirname($vendorDir);
return array( return array(
'HTMLPurifier' => array($vendorDir . '/ezyang/htmlpurifier/library'),
); );

View File

@ -8,7 +8,15 @@ $baseDir = dirname($vendorDir);
return array( return array(
'mirzaev\\minimal\\' => array($vendorDir . '/mirzaev/minimal/mirzaev/minimal/system'), 'mirzaev\\minimal\\' => array($vendorDir . '/mirzaev/minimal/mirzaev/minimal/system'),
'mirzaev\\calculator\\' => array($baseDir . '/mirzaev/calculator/system'), 'mirzaev\\calculator\\' => array($baseDir . '/mirzaev/calculator/system'),
'ZipStream\\' => array($vendorDir . '/maennchen/zipstream-php/src'),
'Twig\\' => array($vendorDir . '/twig/twig/src'), 'Twig\\' => array($vendorDir . '/twig/twig/src'),
'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'), 'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'),
'Symfony\\Polyfill\\Ctype\\' => array($vendorDir . '/symfony/polyfill-ctype'), 'Symfony\\Polyfill\\Ctype\\' => array($vendorDir . '/symfony/polyfill-ctype'),
'Psr\\SimpleCache\\' => array($vendorDir . '/psr/simple-cache/src'),
'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src', $vendorDir . '/psr/http-factory/src'),
'Psr\\Http\\Client\\' => array($vendorDir . '/psr/http-client/src'),
'PhpOffice\\PhpSpreadsheet\\' => array($vendorDir . '/phpoffice/phpspreadsheet/src/PhpSpreadsheet'),
'MyCLabs\\Enum\\' => array($vendorDir . '/myclabs/php-enum/src'),
'Matrix\\' => array($vendorDir . '/markbaker/matrix/classes/src'),
'Complex\\' => array($vendorDir . '/markbaker/complex/classes/src'),
); );

View File

@ -7,8 +7,9 @@ namespace Composer\Autoload;
class ComposerStaticInitd3c0e906485ab41f428834e64f63b2f8 class ComposerStaticInitd3c0e906485ab41f428834e64f63b2f8
{ {
public static $files = array ( public static $files = array (
'320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php',
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php', '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
'320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php',
'2cffec82183ee1cea088009cef9a6fc3' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier.composer.php',
); );
public static $prefixLengthsPsr4 = array ( public static $prefixLengthsPsr4 = array (
@ -17,6 +18,10 @@ class ComposerStaticInitd3c0e906485ab41f428834e64f63b2f8
'mirzaev\\minimal\\' => 16, 'mirzaev\\minimal\\' => 16,
'mirzaev\\calculator\\' => 19, 'mirzaev\\calculator\\' => 19,
), ),
'Z' =>
array (
'ZipStream\\' => 10,
),
'T' => 'T' =>
array ( array (
'Twig\\' => 5, 'Twig\\' => 5,
@ -26,6 +31,22 @@ class ComposerStaticInitd3c0e906485ab41f428834e64f63b2f8
'Symfony\\Polyfill\\Mbstring\\' => 26, 'Symfony\\Polyfill\\Mbstring\\' => 26,
'Symfony\\Polyfill\\Ctype\\' => 23, 'Symfony\\Polyfill\\Ctype\\' => 23,
), ),
'P' =>
array (
'Psr\\SimpleCache\\' => 16,
'Psr\\Http\\Message\\' => 17,
'Psr\\Http\\Client\\' => 16,
'PhpOffice\\PhpSpreadsheet\\' => 25,
),
'M' =>
array (
'MyCLabs\\Enum\\' => 13,
'Matrix\\' => 7,
),
'C' =>
array (
'Complex\\' => 8,
),
); );
public static $prefixDirsPsr4 = array ( public static $prefixDirsPsr4 = array (
@ -37,6 +58,10 @@ class ComposerStaticInitd3c0e906485ab41f428834e64f63b2f8
array ( array (
0 => __DIR__ . '/../..' . '/mirzaev/calculator/system', 0 => __DIR__ . '/../..' . '/mirzaev/calculator/system',
), ),
'ZipStream\\' =>
array (
0 => __DIR__ . '/..' . '/maennchen/zipstream-php/src',
),
'Twig\\' => 'Twig\\' =>
array ( array (
0 => __DIR__ . '/..' . '/twig/twig/src', 0 => __DIR__ . '/..' . '/twig/twig/src',
@ -49,6 +74,45 @@ class ComposerStaticInitd3c0e906485ab41f428834e64f63b2f8
array ( array (
0 => __DIR__ . '/..' . '/symfony/polyfill-ctype', 0 => __DIR__ . '/..' . '/symfony/polyfill-ctype',
), ),
'Psr\\SimpleCache\\' =>
array (
0 => __DIR__ . '/..' . '/psr/simple-cache/src',
),
'Psr\\Http\\Message\\' =>
array (
0 => __DIR__ . '/..' . '/psr/http-message/src',
1 => __DIR__ . '/..' . '/psr/http-factory/src',
),
'Psr\\Http\\Client\\' =>
array (
0 => __DIR__ . '/..' . '/psr/http-client/src',
),
'PhpOffice\\PhpSpreadsheet\\' =>
array (
0 => __DIR__ . '/..' . '/phpoffice/phpspreadsheet/src/PhpSpreadsheet',
),
'MyCLabs\\Enum\\' =>
array (
0 => __DIR__ . '/..' . '/myclabs/php-enum/src',
),
'Matrix\\' =>
array (
0 => __DIR__ . '/..' . '/markbaker/matrix/classes/src',
),
'Complex\\' =>
array (
0 => __DIR__ . '/..' . '/markbaker/complex/classes/src',
),
);
public static $prefixesPsr0 = array (
'H' =>
array (
'HTMLPurifier' =>
array (
0 => __DIR__ . '/..' . '/ezyang/htmlpurifier/library',
),
),
); );
public static $classMap = array ( public static $classMap = array (
@ -60,6 +124,7 @@ class ComposerStaticInitd3c0e906485ab41f428834e64f63b2f8
return \Closure::bind(function () use ($loader) { return \Closure::bind(function () use ($loader) {
$loader->prefixLengthsPsr4 = ComposerStaticInitd3c0e906485ab41f428834e64f63b2f8::$prefixLengthsPsr4; $loader->prefixLengthsPsr4 = ComposerStaticInitd3c0e906485ab41f428834e64f63b2f8::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInitd3c0e906485ab41f428834e64f63b2f8::$prefixDirsPsr4; $loader->prefixDirsPsr4 = ComposerStaticInitd3c0e906485ab41f428834e64f63b2f8::$prefixDirsPsr4;
$loader->prefixesPsr0 = ComposerStaticInitd3c0e906485ab41f428834e64f63b2f8::$prefixesPsr0;
$loader->classMap = ComposerStaticInitd3c0e906485ab41f428834e64f63b2f8::$classMap; $loader->classMap = ComposerStaticInitd3c0e906485ab41f428834e64f63b2f8::$classMap;
}, null, ClassLoader::class); }, null, ClassLoader::class);

View File

@ -1,5 +1,246 @@
{ {
"packages": [ "packages": [
{
"name": "ezyang/htmlpurifier",
"version": "v4.14.0",
"version_normalized": "4.14.0.0",
"source": {
"type": "git",
"url": "https://github.com/ezyang/htmlpurifier.git",
"reference": "12ab42bd6e742c70c0a52f7b82477fcd44e64b75"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/12ab42bd6e742c70c0a52f7b82477fcd44e64b75",
"reference": "12ab42bd6e742c70c0a52f7b82477fcd44e64b75",
"shasum": ""
},
"require": {
"php": ">=5.2"
},
"time": "2021-12-25T01:21:49+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-0": {
"HTMLPurifier": "library/"
},
"files": [
"library/HTMLPurifier.composer.php"
],
"exclude-from-classmap": [
"/library/HTMLPurifier/Language/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"LGPL-2.1-or-later"
],
"authors": [
{
"name": "Edward Z. Yang",
"email": "admin@htmlpurifier.org",
"homepage": "http://ezyang.com"
}
],
"description": "Standards compliant HTML filter written in PHP",
"homepage": "http://htmlpurifier.org/",
"keywords": [
"html"
],
"support": {
"issues": "https://github.com/ezyang/htmlpurifier/issues",
"source": "https://github.com/ezyang/htmlpurifier/tree/v4.14.0"
},
"install-path": "../ezyang/htmlpurifier"
},
{
"name": "maennchen/zipstream-php",
"version": "2.1.0",
"version_normalized": "2.1.0.0",
"source": {
"type": "git",
"url": "https://github.com/maennchen/ZipStream-PHP.git",
"reference": "c4c5803cc1f93df3d2448478ef79394a5981cc58"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/c4c5803cc1f93df3d2448478ef79394a5981cc58",
"reference": "c4c5803cc1f93df3d2448478ef79394a5981cc58",
"shasum": ""
},
"require": {
"myclabs/php-enum": "^1.5",
"php": ">= 7.1",
"psr/http-message": "^1.0",
"symfony/polyfill-mbstring": "^1.0"
},
"require-dev": {
"ext-zip": "*",
"guzzlehttp/guzzle": ">= 6.3",
"mikey179/vfsstream": "^1.6",
"phpunit/phpunit": ">= 7.5"
},
"time": "2020-05-30T13:11:16+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-4": {
"ZipStream\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Paul Duncan",
"email": "pabs@pablotron.org"
},
{
"name": "Jonatan Männchen",
"email": "jonatan@maennchen.ch"
},
{
"name": "Jesse Donat",
"email": "donatj@gmail.com"
},
{
"name": "András Kolesár",
"email": "kolesar@kolesar.hu"
}
],
"description": "ZipStream is a library for dynamically streaming dynamic zip files from PHP without writing to the disk at all on the server.",
"keywords": [
"stream",
"zip"
],
"support": {
"issues": "https://github.com/maennchen/ZipStream-PHP/issues",
"source": "https://github.com/maennchen/ZipStream-PHP/tree/master"
},
"funding": [
{
"url": "https://opencollective.com/zipstream",
"type": "open_collective"
}
],
"install-path": "../maennchen/zipstream-php"
},
{
"name": "markbaker/complex",
"version": "3.0.1",
"version_normalized": "3.0.1.0",
"source": {
"type": "git",
"url": "https://github.com/MarkBaker/PHPComplex.git",
"reference": "ab8bc271e404909db09ff2d5ffa1e538085c0f22"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/MarkBaker/PHPComplex/zipball/ab8bc271e404909db09ff2d5ffa1e538085c0f22",
"reference": "ab8bc271e404909db09ff2d5ffa1e538085c0f22",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0"
},
"require-dev": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
"phpcompatibility/php-compatibility": "^9.0",
"phpunit/phpunit": "^7.0 || ^8.0 || ^9.3",
"squizlabs/php_codesniffer": "^3.4"
},
"time": "2021-06-29T15:32:53+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-4": {
"Complex\\": "classes/src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mark Baker",
"email": "mark@lange.demon.co.uk"
}
],
"description": "PHP Class for working with complex numbers",
"homepage": "https://github.com/MarkBaker/PHPComplex",
"keywords": [
"complex",
"mathematics"
],
"support": {
"issues": "https://github.com/MarkBaker/PHPComplex/issues",
"source": "https://github.com/MarkBaker/PHPComplex/tree/3.0.1"
},
"install-path": "../markbaker/complex"
},
{
"name": "markbaker/matrix",
"version": "3.0.0",
"version_normalized": "3.0.0.0",
"source": {
"type": "git",
"url": "https://github.com/MarkBaker/PHPMatrix.git",
"reference": "c66aefcafb4f6c269510e9ac46b82619a904c576"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/MarkBaker/PHPMatrix/zipball/c66aefcafb4f6c269510e9ac46b82619a904c576",
"reference": "c66aefcafb4f6c269510e9ac46b82619a904c576",
"shasum": ""
},
"require": {
"php": "^7.1 || ^8.0"
},
"require-dev": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
"phpcompatibility/php-compatibility": "^9.0",
"phpdocumentor/phpdocumentor": "2.*",
"phploc/phploc": "^4.0",
"phpmd/phpmd": "2.*",
"phpunit/phpunit": "^7.0 || ^8.0 || ^9.3",
"sebastian/phpcpd": "^4.0",
"squizlabs/php_codesniffer": "^3.4"
},
"time": "2021-07-01T19:01:15+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-4": {
"Matrix\\": "classes/src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mark Baker",
"email": "mark@demon-angel.eu"
}
],
"description": "PHP Class for working with matrices",
"homepage": "https://github.com/MarkBaker/PHPMatrix",
"keywords": [
"mathematics",
"matrix",
"vector"
],
"support": {
"issues": "https://github.com/MarkBaker/PHPMatrix/issues",
"source": "https://github.com/MarkBaker/PHPMatrix/tree/3.0.0"
},
"install-path": "../markbaker/matrix"
},
{ {
"name": "mirzaev/minimal", "name": "mirzaev/minimal",
"version": "2.0.x-dev", "version": "2.0.x-dev",
@ -47,6 +288,399 @@
}, },
"install-path": "../mirzaev/minimal" "install-path": "../mirzaev/minimal"
}, },
{
"name": "myclabs/php-enum",
"version": "1.8.3",
"version_normalized": "1.8.3.0",
"source": {
"type": "git",
"url": "https://github.com/myclabs/php-enum.git",
"reference": "b942d263c641ddb5190929ff840c68f78713e937"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/myclabs/php-enum/zipball/b942d263c641ddb5190929ff840c68f78713e937",
"reference": "b942d263c641ddb5190929ff840c68f78713e937",
"shasum": ""
},
"require": {
"ext-json": "*",
"php": "^7.3 || ^8.0"
},
"require-dev": {
"phpunit/phpunit": "^9.5",
"squizlabs/php_codesniffer": "1.*",
"vimeo/psalm": "^4.6.2"
},
"time": "2021-07-05T08:18:36+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-4": {
"MyCLabs\\Enum\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP Enum contributors",
"homepage": "https://github.com/myclabs/php-enum/graphs/contributors"
}
],
"description": "PHP Enum implementation",
"homepage": "http://github.com/myclabs/php-enum",
"keywords": [
"enum"
],
"support": {
"issues": "https://github.com/myclabs/php-enum/issues",
"source": "https://github.com/myclabs/php-enum/tree/1.8.3"
},
"funding": [
{
"url": "https://github.com/mnapoli",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/myclabs/php-enum",
"type": "tidelift"
}
],
"install-path": "../myclabs/php-enum"
},
{
"name": "phpoffice/phpspreadsheet",
"version": "1.20.0",
"version_normalized": "1.20.0.0",
"source": {
"type": "git",
"url": "https://github.com/PHPOffice/PhpSpreadsheet.git",
"reference": "44436f270bb134b4a94670f3d020a85dfa0a3c02"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/44436f270bb134b4a94670f3d020a85dfa0a3c02",
"reference": "44436f270bb134b4a94670f3d020a85dfa0a3c02",
"shasum": ""
},
"require": {
"ext-ctype": "*",
"ext-dom": "*",
"ext-fileinfo": "*",
"ext-gd": "*",
"ext-iconv": "*",
"ext-libxml": "*",
"ext-mbstring": "*",
"ext-simplexml": "*",
"ext-xml": "*",
"ext-xmlreader": "*",
"ext-xmlwriter": "*",
"ext-zip": "*",
"ext-zlib": "*",
"ezyang/htmlpurifier": "^4.13",
"maennchen/zipstream-php": "^2.1",
"markbaker/complex": "^3.0",
"markbaker/matrix": "^3.0",
"php": "^7.3 || ^8.0",
"psr/http-client": "^1.0",
"psr/http-factory": "^1.0",
"psr/simple-cache": "^1.0"
},
"require-dev": {
"dealerdirect/phpcodesniffer-composer-installer": "dev-master",
"dompdf/dompdf": "^1.0",
"friendsofphp/php-cs-fixer": "^3.2",
"jpgraph/jpgraph": "^4.0",
"mpdf/mpdf": "^8.0",
"phpcompatibility/php-compatibility": "^9.3",
"phpstan/phpstan": "^1.1",
"phpstan/phpstan-phpunit": "^1.0",
"phpunit/phpunit": "^8.5 || ^9.0",
"squizlabs/php_codesniffer": "^3.6",
"tecnickcom/tcpdf": "^6.4"
},
"suggest": {
"dompdf/dompdf": "Option for rendering PDF with PDF Writer (doesn't yet support PHP8)",
"jpgraph/jpgraph": "Option for rendering charts, or including charts with PDF or HTML Writers",
"mpdf/mpdf": "Option for rendering PDF with PDF Writer",
"tecnickcom/tcpdf": "Option for rendering PDF with PDF Writer (doesn't yet support PHP8)"
},
"time": "2021-11-23T15:23:42+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-4": {
"PhpOffice\\PhpSpreadsheet\\": "src/PhpSpreadsheet"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Maarten Balliauw",
"homepage": "https://blog.maartenballiauw.be"
},
{
"name": "Mark Baker",
"homepage": "https://markbakeruk.net"
},
{
"name": "Franck Lefevre",
"homepage": "https://rootslabs.net"
},
{
"name": "Erik Tilt"
},
{
"name": "Adrien Crivelli"
}
],
"description": "PHPSpreadsheet - Read, Create and Write Spreadsheet documents in PHP - Spreadsheet engine",
"homepage": "https://github.com/PHPOffice/PhpSpreadsheet",
"keywords": [
"OpenXML",
"excel",
"gnumeric",
"ods",
"php",
"spreadsheet",
"xls",
"xlsx"
],
"support": {
"issues": "https://github.com/PHPOffice/PhpSpreadsheet/issues",
"source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/1.20.0"
},
"install-path": "../phpoffice/phpspreadsheet"
},
{
"name": "psr/http-client",
"version": "1.0.1",
"version_normalized": "1.0.1.0",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-client.git",
"reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/http-client/zipball/2dfb5f6c5eff0e91e20e913f8c5452ed95b86621",
"reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621",
"shasum": ""
},
"require": {
"php": "^7.0 || ^8.0",
"psr/http-message": "^1.0"
},
"time": "2020-06-29T06:28:15+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
"Psr\\Http\\Client\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common interface for HTTP clients",
"homepage": "https://github.com/php-fig/http-client",
"keywords": [
"http",
"http-client",
"psr",
"psr-18"
],
"support": {
"source": "https://github.com/php-fig/http-client/tree/master"
},
"install-path": "../psr/http-client"
},
{
"name": "psr/http-factory",
"version": "1.0.1",
"version_normalized": "1.0.1.0",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-factory.git",
"reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/http-factory/zipball/12ac7fcd07e5b077433f5f2bee95b3a771bf61be",
"reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be",
"shasum": ""
},
"require": {
"php": ">=7.0.0",
"psr/http-message": "^1.0"
},
"time": "2019-04-30T12:38:16+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
"Psr\\Http\\Message\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common interfaces for PSR-7 HTTP message factories",
"keywords": [
"factory",
"http",
"message",
"psr",
"psr-17",
"psr-7",
"request",
"response"
],
"support": {
"source": "https://github.com/php-fig/http-factory/tree/master"
},
"install-path": "../psr/http-factory"
},
{
"name": "psr/http-message",
"version": "1.0.1",
"version_normalized": "1.0.1.0",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-message.git",
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"time": "2016-08-06T14:39:51+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
"Psr\\Http\\Message\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common interface for HTTP messages",
"homepage": "https://github.com/php-fig/http-message",
"keywords": [
"http",
"http-message",
"psr",
"psr-7",
"request",
"response"
],
"support": {
"source": "https://github.com/php-fig/http-message/tree/master"
},
"install-path": "../psr/http-message"
},
{
"name": "psr/simple-cache",
"version": "1.0.1",
"version_normalized": "1.0.1.0",
"source": {
"type": "git",
"url": "https://github.com/php-fig/simple-cache.git",
"reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b",
"reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"time": "2017-10-23T01:57:42+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
"Psr\\SimpleCache\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common interfaces for simple caching",
"keywords": [
"cache",
"caching",
"psr",
"psr-16",
"simple-cache"
],
"support": {
"source": "https://github.com/php-fig/simple-cache/tree/master"
},
"install-path": "../psr/simple-cache"
},
{ {
"name": "symfony/polyfill-ctype", "name": "symfony/polyfill-ctype",
"version": "v1.23.0", "version": "v1.23.0",

View File

@ -1,24 +1,60 @@
<?php return array ( <?php return array (
'root' => 'root' =>
array ( array (
'pretty_version' => '1.0.0+no-version-set', 'pretty_version' => 'dev-stable',
'version' => '1.0.0.0', 'version' => 'dev-stable',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => NULL, 'reference' => '503e25647cabfd80c98a1ca571a98e4b0595b729',
'name' => 'mirzaev/calculator', 'name' => 'mirzaev/calculator',
), ),
'versions' => 'versions' =>
array ( array (
'mirzaev/calculator' => 'ezyang/htmlpurifier' =>
array ( array (
'pretty_version' => '1.0.0+no-version-set', 'pretty_version' => 'v4.14.0',
'version' => '1.0.0.0', 'version' => '4.14.0.0',
'aliases' => 'aliases' =>
array ( array (
), ),
'reference' => NULL, 'reference' => '12ab42bd6e742c70c0a52f7b82477fcd44e64b75',
),
'maennchen/zipstream-php' =>
array (
'pretty_version' => '2.1.0',
'version' => '2.1.0.0',
'aliases' =>
array (
),
'reference' => 'c4c5803cc1f93df3d2448478ef79394a5981cc58',
),
'markbaker/complex' =>
array (
'pretty_version' => '3.0.1',
'version' => '3.0.1.0',
'aliases' =>
array (
),
'reference' => 'ab8bc271e404909db09ff2d5ffa1e538085c0f22',
),
'markbaker/matrix' =>
array (
'pretty_version' => '3.0.0',
'version' => '3.0.0.0',
'aliases' =>
array (
),
'reference' => 'c66aefcafb4f6c269510e9ac46b82619a904c576',
),
'mirzaev/calculator' =>
array (
'pretty_version' => 'dev-stable',
'version' => 'dev-stable',
'aliases' =>
array (
),
'reference' => '503e25647cabfd80c98a1ca571a98e4b0595b729',
), ),
'mirzaev/minimal' => 'mirzaev/minimal' =>
array ( array (
@ -29,6 +65,60 @@
), ),
'reference' => 'b6f90b700116f20fe48725166ddfb8f6d27ae52d', 'reference' => 'b6f90b700116f20fe48725166ddfb8f6d27ae52d',
), ),
'myclabs/php-enum' =>
array (
'pretty_version' => '1.8.3',
'version' => '1.8.3.0',
'aliases' =>
array (
),
'reference' => 'b942d263c641ddb5190929ff840c68f78713e937',
),
'phpoffice/phpspreadsheet' =>
array (
'pretty_version' => '1.20.0',
'version' => '1.20.0.0',
'aliases' =>
array (
),
'reference' => '44436f270bb134b4a94670f3d020a85dfa0a3c02',
),
'psr/http-client' =>
array (
'pretty_version' => '1.0.1',
'version' => '1.0.1.0',
'aliases' =>
array (
),
'reference' => '2dfb5f6c5eff0e91e20e913f8c5452ed95b86621',
),
'psr/http-factory' =>
array (
'pretty_version' => '1.0.1',
'version' => '1.0.1.0',
'aliases' =>
array (
),
'reference' => '12ac7fcd07e5b077433f5f2bee95b3a771bf61be',
),
'psr/http-message' =>
array (
'pretty_version' => '1.0.1',
'version' => '1.0.1.0',
'aliases' =>
array (
),
'reference' => 'f6561bf28d520154e4b0ec72be95418abe6d9363',
),
'psr/simple-cache' =>
array (
'pretty_version' => '1.0.1',
'version' => '1.0.1.0',
'aliases' =>
array (
),
'reference' => '408d5eafb83c57f6365a3ca330ff23aa4a5fa39b',
),
'symfony/polyfill-ctype' => 'symfony/polyfill-ctype' =>
array ( array (
'pretty_version' => 'v1.23.0', 'pretty_version' => 'v1.23.0',