Перейти к публикации

Макросы в Power Mill


Рекомендованные сообщения

проверил, там всё проще - эта команда применяется только к активной границе, и только всего лишь один раз открывать окно редактирования не обязательно  
Ну да, примерно в ту степь. 
Ссылка на сообщение
Поделиться на других сайтах
  • 2 недели спустя...


подскажите по макросу - из стандартного хелпа на английском:
 

 

For example, to declare an array of three strings:
STRING ARRAY MyArray[3] = {'First','Second','Third'}
All the items in the initialisation list must be the same BASIC-TYPE
as the array.
You can access the items of the array by subscripting. The first item in the array is subscript 0. For example:
INT Index = 0
WHILE Index < size(MyArray) {

     PRINT MyArray[index]
     $Index = Index + 1
}

Prints:

First

Second

Third

 

 

как можно понять - макрос должен иметь такой вид:

STRING ARRAY MyArray[3] = {'First','Second','Third'}
INT Index = 0
WHILE Index < size(MyArray) { 
     PRINT MyArray[Index]
     $Index = Index + 1
}

но он на 4-й строке выдаёт ошибку

как заставить его заработать ?

Ссылка на сообщение
Поделиться на других сайтах

подскажите по макросу - из стандартного хелпа на английском:

 

 

как можно понять - макрос должен иметь такой вид:

STRING ARRAY MyArray[3] = {'First','Second','Third'}
INT Index = 0
WHILE Index < size(MyArray) { 
     PRINT MyArray[Index]
     $Index = Index + 1
}

но он на 4-й строке выдаёт ошибку

как заставить его заработать ?

Неверный синтаксис. PRINT = MyArray[index]

Ссылка на сообщение
Поделиться на других сайтах

Неверный синтаксис. PRINT = MyArray[index]

 

спасибо )

 

и ещё нужна помощь  с макросом -

FUNCTION CleanBoundary(string name) {
REAL offset = 1 mm
REAL diam = entity('boundary';name).Tool.Diameter
// Удалить сегменты меньше чем диаметр инстр. 
EDIT BOUNDARY $name SELECT AREA LT $diam 
DELETE BOUNDARY $name SELECTED
//Смещение наружу и внутрь для сглаживания гран. 
EDIT BOUNDARY $name OFFSET $offset
EDIT BOUNDARY $name OFFSET ${-offset}
}
FUNCTION Main(string bound) { 
FOREACH bou IN folder(bound) {
CALL CleanBoundary(bou.Name)
}
}

если этот макрос запустить  из командной строки, как - macro 111 "20"

то макрос выполняется, но ничего изменяется

а он же должен удалить маленькую границу, которая меньше чем Д инструмента

как заставить работать этот макрос ?

 

и ещё вопрос: тут в цикле FOREACH папка границ пишется как bound

она аналогична имени boundary ? я имею в виду корневую папку границ в проводнике

 

 

и по другому макросу вопрос -

STRING CountToThree = One + ", " + Two + ", " + Three 
PRINT = CountToThree

при запуске пишет - не удаётся понять выражение

как его заставить заработать ?

 

 

PS: и примечание от меня по оператору SWITCH

Пример по изменению типа распределения точек не работает, пока его не вставить например в цикл

FOREACH ent IN folder("toolpath") {
ACTIVATE TOOLPATH $ent.Name

....................................................

EDIT TOOLPATH ; REAPPLY
}

в руководстве даже намёка на это нет, приходится догадываться самому

эх, тяжело для начинающих изучать макросы с такими примерами

Ссылка на сообщение
Поделиться на других сайтах

и ещё вопрос - по циклу WHILE

STRING Fset = 'Top' 
INT Count = 0

WHILE Count < 2 {
ACTIVATE FEATURESET $Fset
ACTIVATE WORKPLANE FROMENTITY FEATURESET $Fset
IMPORT TEMPLATE ENTITY TOOLPATH "Drilling\Drilling.ptf" 
EDIT TOOLPATH $TpName CALCULATE
$Fset = 'Bottom'
$Count = Count + 1
}

макрос выдаёт ошибку

 

PS: Решено: исправил строку

EDIT TOOLPATH $TpName CALCULATE

на

EDIT TOOLPATH ; CALCULATE

теперь работает

 

PPS: ох и сколько ж тут ошибок/опечаток

Изменено пользователем eksodus
Ссылка на сообщение
Поделиться на других сайтах

и ещё одна ошибка

макрос:

FUNCTION Calculate(STRING TpName) {

IF NOT active(entity('toolpath',TpName).Tool.TipRadius)
{
// Ошибка, если траектория не использует 
// скруглённый инструмент
PRINT "Траектория не содержит скруглённый инстр." 
RETURN
}

EDIT TOOLPATH ; CALCULATE
}

FUNCTION Main() {

FOREACH tp IN folder('Toolpath') { 
ACTIVATE TOOLPATH $tp.Name)
}
}

говорит что нет функции Main

при исправлении же

ACTIVATE TOOLPATH $tp.Name)

на

ACTIVATE TOOLPATH $tp.Name

просто ничего не происходит, хотя траектория должна вычисляться, судя по макросу

как  исправить данный макрос ?

Изменено пользователем eksodus
Ссылка на сообщение
Поделиться на других сайтах

и ещё одна непонятка, вот макрос:

FOREACH item IN components(entity('ncprogram','')) {
// only check nctoolpath items
IF lcase(item.RootType) == 'nctoolpath' {
// If the area clearance parameter is active then use flood
IF active(entity('toolpath',item.Name).AreaClearance) {
$item.Coolant.Value = "flood"
} else {
$item.Coolant.Value = "mist"
}
}
}

запускаю макрос, ошибок нет, охлаждение в траекториях не меняется
охлаждение в траекториях в NC  файле меняется только тогда, когда зайти в параметры NC  файла, и вручную выбрать для каждой траектории любое охлаждение, и нажать выполнить

только после этого макрос срабатывает

 

как сделать чтобы этот макрос срабатывал сразу ?

может добавить какую-то команду ?

Ссылка на сообщение
Поделиться на других сайтах

И ещё один вопрос, вот из руководства по макросам:

In other cases, you may want convert a real number to an integer, or an integer to a real number:

INT a = 2 
INT b = 3 
REAL z = 0
$z = a/b 
PRINT $z

This prints 0.0.

If you want the ratio then you have to convert either a or b to real
within the assignment expression.

INT a = 2 
INT b = 3 
REAL z = 0
$z = real(a)/b 
PRINT $z

This prints 0.666667.

То есть, в первом варианте должен быть выведен 0, а во втором - 0,666667

А в реальности выводится и в первом и во втором варианте  - 0,666667

Где там ошибка в первом варианте ?

 

 

и последнее, этот макрос:

REAL maxz = -100000
REAL minz = abs(maxz)
FOREACH item IN components(entity('ncprogram','')) { 
   IF item.RootType == 'nctoolpath' {
     $maxz = max(maxz,entity('toolpath',item.Name))
     $minz = min(minz,entity('toolpath',item.Name))
  }
}
MESSAGE info "Min = " + string(minz) + ", Max = " + string(maxz)

выдаёт ошибку: Не удаётся понять выражение.

Строка 5.

Как это исправить ?

(в строке 6 - аналогичная ошибка, просто макрос до неё не доходит)

 

Помогите найти русское руководство по макросам к PowerMill 2012

ну я вот почти перевёл, осталось вот эти ошибки исправить и чуток дооформить

подожди немного, выложу как всё сделаю

 

Изменено пользователем eksodus
Ссылка на сообщение
Поделиться на других сайтах

Буду очень ждать. Хочу создать макрос, который бы устанавливал СК в середину заготовки. Но не могу понять как мне указать нужную мне точку. Получается, что макрос должен быть интерактивным.  Он приостанавливает свое действие в тот момент, когда мне нужно указать точку. После указания мной точки макрос продолжает работу.

Изучение макросов начал совсем недавно. Случайно узнал о такой возможности. Попробовал записать макрос на траекторию черновой обработки - Выборка 3Д модели... Получилось, на другие записал. Все отлично работает. А то раньше каждый раз приходилось настраивать обработку со значений по умолчанию на свои. А это 4-5 программ в день... Сейчас намного быстрее создаются программы.

Ссылка на сообщение
Поделиться на других сайтах
Получается, что макрос должен быть интерактивным.  Он приостанавливает свое действие в тот момент, когда мне нужно указать точку. После указания мной точки макрос продолжает работу.

это появилось только в 2013 милле

так что тебе нужен другой способ- например поделить макрос на 2 части

первая часть выполняет свои команды и запускает процесс создания СК по заготовке

а ты уже вручную досоздаёшь СК, и потом запускаешь вторую часть

 

Хочу создать макрос, который бы устанавливал СК в середину заготовки. Но не могу понять как мне указать нужную мне точку.

может через переменные min и max, в твоём случае - minx miny maxx maxy

по принципу - вычислить абсолютные и относительные  размеры заготовки,

и поместить СК в точке, равной половине абсолютного значения заготовки по каждой оси?

 

параметр для задания СК - {workplane}.Origin

 

А то раньше каждый раз приходилось настраивать обработку со значений по умолчанию на свои.

можно ещё создать траекторию, или несколько, выставить нужные параметры

создать инструменты и границы и тд - и сохранить всё это как шаблон окружения,

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

и написать ещё макрос - который будет для каждой траектории вычислять заготовку, границы и потом траектории

 

я похожие детали, с разными размерами, обрабатываю сохраняя и потом вставляя шаблон окружения

Изменено пользователем eksodus
Ссылка на сообщение
Поделиться на других сайтах

Буду отвечать по возможности.

Тут правим:

 

 

FUNCTION CleanBoundary(string name) { REAL offset = 1 mm REAL diam = entity('boundary';name).Tool.Diameter // Удалить сегменты меньше чем диаметр инстр. EDIT BOUNDARY $name SELECT AREA LT $diam DELETE BOUNDARY $name SELECTED //Смещение наружу и внутрь для сглаживания гран. EDIT BOUNDARY $name OFFSET $offset EDIT BOUNDARY $name OFFSET ${-offset} } FUNCTION Main(string bound) { FOREACH bou IN folder(bound) { CALL CleanBoundary(bou.Name) } }

В строке FOREACH изменяем: FOREACH bou IN folder ('Boundary\'+bound)

В противном случа милл просто не знает, в в каком разделе лежит папка bound. А так мы ему говорим, что папка bound лежит в границах



STRING CountToThree = One + ", " + Two + ", " + Three 
PRINT = CountToThree

Это две последние строчки макроса. Сам макрос такой:

STRING One = "One"
STRING Two = "Two"
STRING Three = "Three"
STRING CountToThree = One + ", " + Two + ", " + Three
PRINT = CountToThree

и ещё одна ошибка


как  исправить данный макрос ?

Скобка в строке Activate функции Main точно лишняя. В остальном у меня все работает.


и ещё одна непонятка, вот макрос:

FOREACH item IN components(entity('ncprogram','')) {
// only check nctoolpath items
IF lcase(item.RootType) == 'nctoolpath' {
// If the area clearance parameter is active then use flood
IF active(entity('toolpath',item.Name).AreaClearance) {
$item.Coolant.Value = "flood"
} else {
$item.Coolant.Value = "mist"
}
}
}

 

Макрос рабочий. В макросе проверяется условие, является ли траектория Выборкой. Если да, то режим сож изменяется.


И ещё один вопрос, вот из руководства по макросам:

 

Чушь, конечно, в руководстве. Переменные а и b - целочистенные, z - действительно. Поэтому если a разделить на b, то получится все равно действительное, поэтому z = 0.66667. Если нужно получить целочисленный результат деления, то нужно это указать, т.е. либо задать не REAL z, а INT z при объявлении, либо конвертировать результат деления, т.е. z = int(a/b).

Суммарно

INT a = 2
INT b = 3
REAL z = 0
$z = a/b
PRINT $z 

Ответ: 0,66667

INT a = 2
INT b = 3
REAL z = 0
$z = int(a/b)
PRINT $z

Ответ: 0

 

ИЛИ

INT a = 2
INT b = 3
INT z = 0
$z = a/b
PRINT $z

Ответ: 0

Изменено пользователем Kinematik
Ссылка на сообщение
Поделиться на других сайтах
Это две последние строчки макроса. Сам макрос такой:

да, спасибо

 

 

Скобка в строке Activate функции Main точно лишняя. В остальном у меня все работает.

хорошо, если в данном макросе убрать скобку - то повермилл ошибок не выдаёт

FUNCTION Calculate(STRING TpName) {

IF NOT active(entity('toolpath',TpName).Tool.TipRadius)
{
// Ошибка, если траектория не использует 
// скруглённый инструмент
PRINT "Траектория не содержит скруглённый инстр."
RETURN
}

EDIT TOOLPATH ; CALCULATE
}

FUNCTION Main() {

FOREACH tp IN folder('Toolpath') {
ACTIVATE TOOLPATH $tp.Name
}
}

но не работает он как надо - ничего не вычисляется

да, ошибок нет, - но вычисления не происходит

проверяю все макросы конечно же на реальном проекте - то есть создаю модель, границы, нс-файлы, траектории, папки и тд

так вот - в реальном проекте ничего не вычисляется, только траектории активируются по очереди

 

PS: оказалось тут в функции Main нет вызова функции Calculate

если изменить её на

FUNCTION Main() {
   FOREACH tp IN folder('Toolpath') {
   ACTIVATE TOOLPATH $tp.Name
   CALL Calculate(tp.Name)
 }
}

то вычисления теперь происходят

и ещё надо было закрывающую скобку в операторе IF  перенести на пред строку

 

хорошо, эти два макроса теперь исправлены

Изменено пользователем eksodus
Ссылка на сообщение
Поделиться на других сайтах

Если нужно получить целочисленный результат деления, то нужно это указать, т.е. либо задать не REAL z, а INT z при объявлении, либо конвертировать результат деления, т.е. z = int(a/b)

спасибо, это тоже теперь выводит правильно всё

 

 

 

и ещё одна непонятка, вот макрос:

FOREACH item IN components(entity('ncprogram','')) {
// only check nctoolpath items
IF lcase(item.RootType) == 'nctoolpath' {
// If the area clearance parameter is active then use flood
IF active(entity('toolpath',item.Name).AreaClearance) {
$item.Coolant.Value = "flood"
} else {
$item.Coolant.Value = "mist"
}
}
}

 

Макрос рабочий. В макросе проверяется условие, является ли траектория Выборкой. Если да, то режим сож изменяется.

 

 

 

не совсем так - если Выборка, то режим меняется на Полив

для всех остальных - Туман

а по умолчанию везде стоит - Стандартное

так что меняться будет для всех траекторий

 

но тут вопрос в другом - как я уже писал, и сейчас вот ещё раз перепроверил - макрос то рабочий, но срабатывает он не с первого раза (почему так ?)

и самое главное - значения охлаждения НЕ сохраняются

то есть если и поменялись значения - то если активировать и перейти в другой Нс-файл, и потом вернуться обратно - то все значения сбрасываются на Стандартное

 

значения сохраняются только в том случае - если перед этим вручную выбрать для каждой траектории, пусть даже то что стоит по умолчанию - Стандартное

и теперь после запуска макроса значения меняются на те что нужно, и после перевыбора других НС файлов значения охлаждения сохраняются

 

а бывает что значения и совсем не меняются, пока вручную не сделать выбора охлаждения перед этим

почему так ? и это вопрос наверное к миллу, а не к макросу ?

 

и ещё одно - макрос срабатывает только к активному НС файлу

если все НС файлы неактивны - выдаёт ошибку

 

а если даже вставить в цикл -

FOREACH ent IN folder("ncprogram") {
ACTIVATE ncprogram $ent.Name

...............................................

NCTOOLPATH APPLY
NCTOOLPATH ACCEPT FORM ACCEPT NCTOOLPATHLIST
}

то без предварительного ручного перевыбора типа охлаждения ничего не меняется

почему вручную надо выбирать, чтобы макрос сработал ?

 

PowerMILL 2012

 

 

 

 

 

 

Ссылка на сообщение
Поделиться на других сайтах

PowerMILL 2012

Это хорошая оговорка ))) У меня же 2016, так что макросы могут по-разному работать. Установлю себе 2012, отвечу

Ссылка на сообщение
Поделиться на других сайтах

Итак - перевод полностью завершён.

Сконвертировал в пдф-ку. Но перед тем как выложить хочу исправить ещё пару ошибок

 

Это хорошая оговорка ))) У меня же 2016, так что макросы могут по-разному работать. Установлю себе 2012, отвечу

 

макрос с изменением типа охлаждения можно оставить как есть - кому надо будет сильно - сам разберётся

а вот два макроса есть нерабочие

один, как я уже писал выше - выдаёт ошибку:

REAL maxz = -100000
REAL minz = abs(maxz)
FOREACH item IN components(entity('ncprogram','')) {
IF item.RootType == 'nctoolpath' {
$maxz = max(maxz,entity('toolpath',item.Name))
$minz = min(minz,entity('toolpath',item.Name))
}
}
MESSAGE info "Min = " + string(minz) + ", Max = " + string(maxz)

ошибка в 5 строке - $maxz которая

 

и второй макрос ошибки не выдаёт, но ничего не происходит:

FUNCTION CleanBoundary(string name) {
     REAL offset = 1 mm
     REAL diam = entity('boundary';name).Tool.Diameter
     // Удалить сегменты меньше чем диаметр инстр. 
     EDIT BOUNDARY $name SELECT AREA LT $diam
     DELETE BOUNDARY $name SELECTED
     //Смещение наружу и внутрь для сглаживания гран. 
     EDIT BOUNDARY $name OFFSET $offset
     EDIT BOUNDARY $name OFFSET ${-offset}
   }
FUNCTION Main(string bound) {
     FOREACH bou IN folder(bound) {
     CALL CleanBoundary(bou.Name)
   }
}

Кинематик, если даже заменить строку как ты говорил на FOREACH bou IN folder ('Boundary\'+bound) -

то всё равно ничего не происходит. То есть маленькие участки границ не удаляются, и смещение не выполняется +-  1 мм.

Ну то есть ошибок нет, но и не работает макрос.

Вот птф-ка от 2012 милла и dgk границы - попробуй, у меня этот макрос не работает.

Или может я что-то не так делаю ?

 

PS: конечно можно изменить макрос на типа:

FOREACH ent IN folder("boundary") {
ACTIVATE Boundary $ent.Name      
REAL offset = 1 mm
     REAL diam = 5
     EDIT BOUNDARY $ent.Name  SELECT AREA LT 1
     DELETE BOUNDARY $ent.Name SELECTED
     EDIT BOUNDARY $ent.Name OFFSET $offset
     EDIT BOUNDARY $name OFFSET ${-offset}
   }

тогда всё работает

ну и вместо REAL diam = 5 можно запрос сделать, или задать чтобы использовался активный инструмент

но в руководстве по макросам объясняется функция Main - это будет тогда некорректным примером

Bound.zip

Ссылка на сообщение
Поделиться на других сайтах

неужели никто больше не пользуется макросами ?

Кинематик занят, а остальные молчат

 

Ну ладно, чтобы не затягивать надолго время  -

вот полная русская версия Руководства по марокпрограммированию для милла 2012

 

Примечание:

Макросы на 50-52 страницах не работают - просто ничего не происходит. (возможно, я их неправильно запускаю)

Макрос на 84 странице - выдаёт ошибку.

 

Все остальные макросы в примерах работают.

PowerMILL 2012 - Макропрограммирование.pdf

Ссылка на сообщение
Поделиться на других сайтах

Если мануаль на русском то все начнут изучать макросы . спсасибо :smile:

Ссылка на сообщение
Поделиться на других сайтах

готовлю пакет макросов для всеобщего пользования, те с котрыми работаю сам (около 30шт),+ меню пользователя, значительно ускоряющих работу повер мила.

Ссылка на сообщение
Поделиться на других сайтах

Есть ли макросы позволяющие автоматически разделить по слоям вертикальные/горизонтальные поверхности, поверхности перпендикулярные плоскости ХУ (отверстия, пазы, окна)?

Ссылка на сообщение
Поделиться на других сайтах
  • MFS закрепил это тему

Присоединяйтесь к обсуждению

Вы можете опубликовать сообщение сейчас, а зарегистрироваться позже. Если у вас есть аккаунт, войдите в него для написания от своего имени.
Примечание: вашему сообщению потребуется утверждение модератора, прежде чем оно станет доступным.

Гость
Ответить в тему...

×   Вставлено в виде отформатированного текста.   Вставить в виде обычного текста

  Разрешено не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отобразить как ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставить изображения напрямую. Загрузите или вставьте изображения по ссылке.

  • Сейчас на странице   0 пользователей

    Нет пользователей, просматривающих эту страницу.




  • Сообщения

    • gudstartup
      считывание происходит при помощи вх\вых сигналов контроллера plc 
    • gudstartup
      @Maks Horhe так все таки скиньте бэкап эмулируем ваше чпу в cncguide и посмотрим куда поедет?  можете снять видео с фиксацией координатных позиций после каждого кадра. Выложу вашу программу пусть программисты посмотрят все ли в ней ок. %O0002 G40 G17 G94 G90 G49 G80 N1 G91 G28 Z0.0 N2 G91 G28 X0.0 Y0.0 N3 G91 G28 B0.0 C0.0 N4 M03 S200 N5 G90 G0 G53 B0.0 C0.0 N6 G54 N7 X0.0 Y0.0 N8 G90 G43 H01 N9 G90 G0 X0.0 Y0.0 N10 G90 G0 Z200.0 N11 G01 Z10.0 F1500. N12 M00 N13 G00 Z200.0 N14 G40 G49 G69 N15 G00 G53 Z0.0 N16 G00 G54 B0.0 C0.0 N17 G68.2 X0.0 Y0.0 Z0.0 1135. J39.2044 K-129.2315 N18 G53.1 N19 G01 X0.0 Y0.0 F1500 N20 G90 G43 H01 N21 G90 G01 X0.0 Y0.0 F1500 N22 G90 G01 Z200. F1500 N24 M00 N25 G00 Z200. N26 G40 G49 G69 N27 G91 G28 Z0.0 N28 G28 X0.0 Y0.0 N29 G91 G28 B0.0 C0.0 N30 M5 N31 M30
    • gudstartup
      @karlf 530 считывает ключ по специальному протоколу при помощи plc и получает его серийный номер а из него определяет возможные режимы доступа. там нет драйвера а есть plc модуль или несколько эти модули написаны на питоне  надпись smartkey исчезает с экрана при запуске чпу??
    • ДОБРЯК
      Для того, чтобы получить правильные высшие) формы при виртуальном эксперименте, нужно сделать грамотную КЭ модель. От разговора на эту тему вы постоянно уклоняетесь.  То нет компьютера под рукой, сделать простейший тест, то теряете интерес. :=) Сходимости энергии деформации при расчетах статики, недостаточно для точного определения высших собственных форм и частот.  Для того, чтобы грамотно использовать метод конечных элементов, нужно сделать много-много тестов в статике, динамике и ... Одной кнопки и двух конечных элементов в 3Д программе недостаточно для определения высших собственных форм...  У вас в качестве инструмента всего два конечных элемента, шести узловая несовместная оболочка Тимошенко и десяти узловой тетраэдр. И еще контакты при решении задачи на собственные числа. Вам ли говорить про правильность определения высших собственных форм для сложных изделий... :=)    
    • vad0000
      Покажите схему с разрешением на движение
    • vad0000
      Вход, а не выход Вытащить Аналоговый вход и все, как будто туда ничего не подключено И если мы подключим сигнал к энкодеру оси Х, то он стнтет одинаковый с аналоговым входом, который не подключен?
    • Snake 60
      @waze4534  Посмотрите вверх и прочитайте текст на красной полоске...
    • kkk
      Я так понимаю, что предупреждение про "касательные" не просто так выскакивает. Если скруглить прямую стыковку отрезков эскиза (минимальным радиусом) то все работает даже без объединенной кривой, достаточно эскиза.
    • karlf
      Подскажите пожалуйста, может кто сталкивался. Станок DMU-50 на стойке TNC 530, перестал определяться ключ доступа. Сам ключ вроде работает, если переключать на нём режимы, то в шкафу на соответствующих блоках лампочки тоже переключаются. Но изначально был уровень доступа 4, а теперь уровни доступа не активны. Ключ только один, запасных нет. Есть какой-то старый бэкап, пробовал его накатить, но какой-то он непонятный - станок грузится, но почти в конце загрузки выдаёт какую-то ошибку по параметрам. Может кто знает в каком из разделов и в какой папке искать установленные драйверы ключа?
    • YuriySt54
      В данной конструкции можно сразу одним телом делать и обрезать. Но меня интересовало, можно ли сразу при построении массива ограничить лишнее.
×
×
  • Создать...