Перейти к содержимому

Seryoga

Пользователи
  • Публикации

    100
  • Зарегистрирован

  • Посещение

  • Победитель дней

    6

Сообщения, опубликованные пользователем Seryoga


  1. 32 минуты назад, Krutoy сказал:
    В 01.06.2019 в 17:30, Seryoga сказал:

    Скор --- количество блоков выкопанное за время N
    Действия --- действия робота.
    Состояние --- блоки от робота в радиусе R

    Как определять время N? 

    Действия? То есть мне на вход подавать выходные значения нормализованные до 0..1 ?

    Не, это не входные данные для FFNN, это входные параметры для семейства алгоритмов RL.

    N и R нужно определять исходя из окружения, например если нет гео-анализатора, то R=1, иначе выбирать в зависимости от мощности анализатора. N выбирать в зависимости от качества обучения (параметров сети). Я бы выбрал 10-30 сек на попытку.

    Обычно для сетей обученных данным алгоритмом:
    State[i-H: i] --- входные данные, где H размер истории (опять же выбирается в зависимости от скорости обучения, мощности окружения, мощности компа и тп)
    Actions --- выходной one hot encoded вектор размерности A, где A равно количеству действий. Номер действия равен номеру максимального значения в этом векторе. `Максимального` значения, потому что, обычно, на выходе сети стоит softmax, который создаёт не идеальный one hot вектор.


  2. @Krutoy

    Можешь почитать про Reinforcement Learning. Данный алгоритм обучения нейронных сетей разрабатывался для решения подобных задач: выкопать роботом максимальное количество блоков за ограниченное время. В 2013 рвали NIPS со статьями об нейронных сетях, играющих в atari игры.

    В качестве параметров, я бы выбрал: 
    Скор --- количество блоков выкопанное за время N
    Действия --- действия робота.
    Состояние --- блоки от робота в радиусе R

    ps. Очевидно, что писать проще, чем делать, но должно сработать :)
    pss. Для lua есть библиотека Torch, в которой есть модели для обучения сетей используя Q-learning


  3. Моё скромное мнение (тезисно):

    1. Большая команда с суммарным уровнем программирования ниже среднего;
    2. Явно не все будут увлечены идеей и рано или поздно сольются;
    3. Нужно сделать Totoro направляющим, так как у него есть способность писать issue на каждый чих, что в нашем случае является сильным преимуществом;
    4. На качественное тестирование надеяться глупо;
    5. Нужно выбрать статически типизированный язык, так как количетсво багов в коде завист экспоненциально от количесва людей в команде. Ошибки по типу `AttributeError: 'Class' object has no attribute 'field' ` будут неизбежно. Без должного тестирования их сложно отлавливать;
    6. Нужно выбирать игру с простой мехникой;
    7. Нужно выбирать игру с упором на разнообразие простых фич, так как в команде много человек, которым хочется чего-нибудь простого поделать;
    8. 2d графон, так как очень сложно нарисовать 3d картинку, которая не будет резать глаз человеку из 2018 года;
    9. Нужно выбирать пиксельный стиль, так как даже если сольётся норм художник, его почти каждый сможет заменить;
    10. Механики игры приоритетнее сюжета;
    11. Механики игры приоритетнее графония;
    12. Мультиплеер следует прикручивать в самом конце, если он вообще нужен;
    13. Как было замечено игра с изометрией или с видом сверху лучше, так как взаимодействие объектов с миром примитивное;
    14. Рогалик (данжи) и спейс-шутер удовлетворяют критериям выше;
    15. Движок для этих игр можно написать самостоятельно, так как кроме проверки пересечения кругов и прямоугольников ничего нет;
    16. Игры The Binding of IsaacEnter the Gungeonаркадный спейс-шутерR-Type и тп.
    17. Также если команда самоуверенная, то можно попробовать что-то по типу с Castle Crashers®
    • Нравится 1

  4. 9 минут назад, Xytabich сказал:

     

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

    А почему тогда игру, может что-нибудь другое. Например нормальный lua-plugin для sublime или что-то такое?
    Если я правильно понимаю, то в играх основное --- это дизайн игры и рисование, а не программирование.


  5. 14.10.2018 в 14:16, Totoro сказал:

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

    Если только не делать что-то в стиле SS13.

    Уже есть: FTL: Faster Than Light


  6. Вот важное сообщение: http://computercraft.ru/topic/2128-pishu-novuiu-os/?p=32217

     

    Все остальные сообщения в этой теме -- пустой треп про nautilus, IPC, про сокеты и про другие термины.

     

    Важно сейчас понять, найдется ли 2-3 человека, которые могут находить или даже фиксить баги. Все ради той заветной многопоточности, о которой многие мечтали со времен появления мода

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

     

    http://computercraft.ru/topic/2128-pishu-novuiu-os/?p=32217

    Полазив по этой теме я не нашёл ни одной ссылки на github, bitbucket или ещё на какой-нибудь хостинг кода. Чтобы можно было посмотреть его или скачать и запустить его. =(

    Могу утверждать точно, что найдутся люди, которые пару минут потыкают в твой ui, если ты скинешь ссылку на туториал о том как поставить твой wm. А вот априорно сказать, что кто-то будет намеренно искать баги, невозможно. Так как у всех тут есть учёба, работа или ещё какие-либо дела.

    Вроде как написал Объективное мнение.


  7. На мой взгляд, разрешение ОС-монитора не такое большое, чтобы делить его на окна. Если бы я стал писать многозадачную операционку, разделение экрана я бы реализовал не как в Windows, а как в Androidе. Т.е. из всех запущенных приложение только одно захватывает экран, оно же обрабатывает события мыши и клавы. Остальные приложения крутятся в фоне и если что-то пишут, то на свой виртуальный экран. Но, это лишь мое скромное мнение.


    Эта фича является под фичей фичи 5, которую RccHD обещал сделать.
    Если в i3 нажать 'mode' + W, то все окна примут вид горизонтального стека. Так видно только одно окно, a остальные прячутся за ним:

    jX8c25Ml.png

     

    5. Можешь сделать шапки окошкам и дать возможность окошкам стакаться, разными способами?

    5) да, но на счет шапок не уверен... На маленьких экранах можно будет выключить шапку


  8.  

     

    Сейчас рамка в 1 пиксель, ее можно будет убрать, наверное


    Я имел в виду, что у вас сейчас на разделение тратится 2 пикселя. А можно тратить 1, если сделать рамку общей для соседних окон. То есть сначала размечаем сетку. А затем отдаём ячейки программам на использование.

    Если я не прав в первом утверждении, то не могли бы вы скинуть скриншот текущей версии wm?

  9. Можно как-нибудь пощупать, тот wm что ты сделал?
    Пожелания по тому, что я увидел на скриншотах из поста.

    1. Можешь сделать возможность изменять ширину рамки окна? Например у тебя сейчас у тебя 2 пикселя хотелось бы сделать 1 или вообще убрать
    2. Можешь сделать workspaces и разных пользователей (linux: ctrl + alt + Fi)?
    3. Можешь сделать язык раскладки компьютера независимым от реальной раскладки?
    4. Можешь сделать настраиваемую панель инструментов? Чтобы пользователь сам мог туда поместить номер воркспейса, язык, майн-время, реальное время, кол-во занятой/свободной оперативки и тп.
    5. Можешь сделать шапки окошкам и дать возможность окошкам стакаться, разными способами?
    6. Можешь поддерживать горячие клавиши из i3 и дать возможность создать свои?
    7. Можешь сделать возможность поставить заставку, фон рабочего стола? Так же дать возможность разработчику приложения сделать полупрозрачные окна?
    8. Можешь сделать консоль с настраиваемым шрифтом и фоном?
    9. Можешь сделать полноценную однострочную консоль запускаемую используя горячую клавишу? По типу той что запускается в i3 на 'mode' + D (только в i3 это не консоль, но ты сделай консоль =))
    10. Можешь сделать возможность изменения размеров окна мышкой, а так же дать возможность программисту делать перетаскиваемые окна. Например отчёт об ошибке или предупреждение так лучше выглядит. (окошечко с одной кнопкой ОК)

    А у тебя поддерживаются несколько мониторов?

     

    псы, ты точно пишешь ОС?


  10.  

     

    Да, но такие программы должны слушать событие "screen_resized", чтобы сразу обновить свои переменные в соответствии с новым размером окна. 

    Нормальные программы не должны слушать этот эвент, а должны просто перерисовываться используя значения размера окна. 

  11. Спасибо за пояснение очевидного. Ты забываешь про буфер хешмапы, ускоряющий поиск часто используемых объектов - в большинстве случаев описанные тобой операции банально "скипаются", особенно в нашем контексте, где используется обращение к одним и тем же вложенным таблицам.

    Даже если это так, то ты наверное понимаешь, что это всё равно не сравнимо с чтением объекта по ссылке.


  12. Переменная весит столько, сколько определено ее типом: строки занимают 17 байт + длина самой строки, таблица кушает 40 байт + ее содержимое, каждая функция - 20 байт + локальные данные. Пожалуйста, не пиши глупости без знания матчасти.

    Переменная весит сколько весит ссылка в ОS.

    А вот объект на который ссылается переменная весит в зависимости от типа.

    Как ты понимаешь ссылка это не объект на стеке и она ссылается на объект в твоей мапе который ты и так хранишь.

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


  13. Увы, такой подход крайне нерационален. Безусловно, визуально куда проще выделить локальную переменную под жирную таблицу с множеством вложенных обращений, сэкономив тем самым несколько тиков - однако если бы я использовал такой подход при написании требовательного софта, то он вылетал бы с not enough memory еще до старта. Примером может послужить наш 3D-движок: сборщик мусора банально не успевал очищать локальные переменные-указатели на таблицы векторов при отрисовке сцен, и ошибка о нехватке памяти вылезала как результат. Сократив подобный "некорявый код" до минимума, мы смогли запустить движок всего лишь на 2 МБ RAM. Так что лучше помучиться с лишними буковками, нежели писать неоптимизированное в данном контексте ПО. Имхо, конечно же

    RccHD немного не убедительно написал, я попробую его поправить.

    1. выполнение buffer.currentFrame[index]

       -- обращение к переменной buffer

       -- обращение к полю объекта. Но мы имеем дело с lua, по-этому buffer это HashMap а currentFrame это ключ.

           - расчёт hash("currentFrame")

           - определение смещения по хешу

           - выборка списка (может дерева) элементов по смещению из массива

           - разрешение коллизий (дорого)

           - ...

       -- выборка из полученной таблицы элемента с индексом, что приводит к 'см выше'

       -- если вы 'lucky boss' то разрешение кеш промахов (это очень затратная операция)

    2.  выборка значения переменной

       -- если интерпретатор lua переменную положил на стек, то это бесплатная операция, иначе:

           - чтение данных из ОЗУ (если есть кеш, то это тоже почти бесплатная op)

           - в худшем случае разрешение 1 кеш промаха

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

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

    Но таких проблем быть не должно.

    Мне кажется, что кто-то просто забывает писать ключевое слово local.

    И переменная весит ровно 64 бита.

    Если у вас локальная переменная долго живёт а объект который по ней находится больше не будет использоваться,

    то можно написать var = nil. И gc, по возможности, удалит объект, на который ссылалась переменная.

    А сама ссылка удалится как закончится её область видимости (без gc).

    • В шоке 1

  14. Это топ идея:

    Написать бота который будет искать сервера майна с определёнными модами. 

    На найденном сервере регистрируется и заходит на него.

    Дальше собирает нужное количество ресов и строит робота.

    В робота закладывает программу, которая сможет развернуть ферму с учётом ттх сервера.

    И так в цикле while (true)

    • Нравится 4

  15. Seryoga сказал(а) 23 Июн 2017 - 11:53: Насчёт извращенцев, когда вам потребуется наследовать не все методы из родительского класса?

    Представьте себе, что есть объекты Rect, Triangle и Line. У всех этих объектов может быть общий метод Rotate(x, y, z, angle), который будет унаследован у Figure_prototype.Rotate

    Это вы рассказываете где нужно наследование, а не о том где не нужно наследовать все методы.


    • Чем вам не понравилось стандартное исполнение классов в lua?
    • Можно ли в runtime узнать является ли объект чьим-либо наследником или нет?
    • Создание приватных полей и методов похоже на один огромный костыль.
    • Почему если вы не понимаете зачем нужны те или иные фишки языка, то человек который их использует -- извращенец? Мне кажется вы никогда и ничего не писали на c++ или java. Основное приимущество слов private, public, protected и тп. это статическая или очень ранняя динамическая проверка наличия ошибок в программе. static нужен для создания общей памяти для всех классов. Также эти маркеры помогают размечать память объекта, но для луа это не актуально.
    • Насчёт извращенцев, когда вам потребуется наследовать не все методы из родительского класса?
    • Знаете что такое singleton? Как его создать используя вашу библиотеку? Как создать несколько singleton'ов в одном пакете?
    • Есть класс MyClass. Нужно создать метод класса, который создаёт новый объект класса MyClass и что-то с ним делает. Как это сделать?
    • Как переопределить операторы +, -, / и тп.?
    • Нельзя ли избавиться от двойной скобки, используя vararg?

      ​local Player = Class({
          ...
      })
    • Какой код сложнее?

      local myObject = (function()
          local secretString = "это приватная меременная без всяких заморочек"
       
          return Class({
              -- класс без конструктора
              publicString = "а это публичная переменная!!!"
          })
      end)()
      

      или

      local MyClass = Class({
          "public", public_field = "abc",
          "private", private_field = "def"
      })
    • Как думаете почему создатели языка lua отказались от классов?


  16. "Помогите. Я тут что-то тыкнул, а оно само сломалось. Что делать?"

     

    le1gNEh.png

    WbA6Pad.png

    java.lang.NullPointerException
    	at moonlightowl.openblocks.io.JSON.recreate(JSON.java:105)
    	at moonlightowl.openblocks.OpenBlocks.load(OpenBlocks.java:399)
    	at moonlightowl.openblocks.OpenBlocks.openProject(OpenBlocks.java:423)
    	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    	at java.lang.reflect.Method.invoke(Unknown Source)
    	at sun.reflect.misc.Trampoline.invoke(Unknown Source)
    	at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
    	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    	at java.lang.reflect.Method.invoke(Unknown Source)
    	at sun.reflect.misc.MethodUtil.invoke(Unknown Source)
    	at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1771)
    	at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1657)
    	at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
    	at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
    	at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
    	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
    	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    	at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
    	at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
    	at javafx.event.Event.fireEvent(Event.java:198)
    	at javafx.scene.control.MenuItem.fire(MenuItem.java:462)
    	at com.sun.javafx.scene.control.skin.ContextMenuContent$MenuItemContainer.doSelect(ContextMenuContent.java:1405)
    	at com.sun.javafx.scene.control.skin.ContextMenuContent$MenuItemContainer.lambda$createChildren$343(ContextMenuContent.java:1358)
    	at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218)
    	at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
    	at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
    	at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
    	at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
    	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
    	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    	at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    	at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    	at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
    	at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
    	at javafx.event.Event.fireEvent(Event.java:198)
    	at javafx.scene.Scene$MouseHandler.process(Scene.java:3757)
    	at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3485)
    	at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762)
    	at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494)
    	at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:381)
    	at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:295)
    	at java.security.AccessController.doPrivileged(Native Method)
    	at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$354(GlassViewEventHandler.java:417)
    	at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389)
    	at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:416)
    	at com.sun.glass.ui.View.handleMouseEvent(View.java:555)
    	at com.sun.glass.ui.View.notifyMouse(View.java:937)
    	at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    	at com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191)
    	at java.lang.Thread.run(Unknown Source)

     


    "Ну и не сильно хотелось"

     

    NcRDxqt.pngiIwPCrZ.png


    "Ожидания - Реальность"

    Действие -- Ожидание -- Реальность

    ctrl + S -- сохранить файл -- двинуть полотно вверх

    ctrl + shift + S -- сохранить файл как ... -- двинуть полотно вверх

    ctrl + W -- закрыть файл -- двинуть полотно вниз

    ctrl + A -- выделить всё (двинуть полотно влево) -- выделить всё  ?????????????????

    ctrl + ПКМ -- копировать элемент -- nope
    ПКМ + del -- удалить элемент -- активировать корзину
    scroll -- сдвинуть полотно -- изменить масштаб

    ctrl + [+-] -- изменить масштаб -- nope
    ctrl + F -- поиск элемента -- nope
    ПКМ -- выделить элемент -- nope
    ЛКМ -- получить выпадающий список -- nope
    соединение "портов" -- один драйвер (вывод) много буфферов (вход) -- много драйверов один буффер
    ПКМ на порт -- получить список проводников и достать нужные -- достать только все
    ПКМ и удержание на пустом месте -- движение полотна -- nope

     


    Резюме

    • классная идея
    • нет документации и вообще какого-либо описания. А в таком проекте это самое важное, так как человек, который хочет использовать этот способ написания программ, может совершенно не знать, что такое программирование и с чем его едят.
      • Я 10 мин рисовал "Hello world", при этом заглядывая в код, который генерирует программа, иначе бы мог провозится гораздо дольше.
    • отсутствует многоуровневое описание
    • баги, много багов
      • выделение работатет только от верхнего левого к нижнему правому углу
      • фигня какая-то с проводничками, путаются и не хотят расутываться, улетают в космос
      • создаёт битые файлы
      • можно графически описать не синтезируемый алгоритм
      • создаются пременные, которые нельзя переиспользовать
      • ...

    ps. почитай про: control flow graph и control flow analysis

    • Нравится 1

  17. Если будете пилить что-то масштабное, то не могли бы учесть

    Мои пожелания:

    1. У меня "иногда" появляются свободные деньки, которые не куда деть.
      Было бы прекрасно, если бы я смог посмотреть issues и на основе их сделать небольшой вклад в проект, ввиде парочки pull request'ов.
    2. JS -- это язык программирования не для души.

    ?


  18. А почему нельзя просто прошить код трассирующими маркерами?
    ТО ЕСТЬ возьмём следящий поток и две функции для работы с ним:

    1. mark(*variables)  -- скопировать и отпрвить потоку переменные
    2. wait()                   -- остановка до того пока следящий поток не разрешит продолжить работу

    Вставить функцию mark во всех местах где изменяется какая-либо переменная или если есть вероятность изменения переменной
    Также трассировать глобальные переменные.
    В мастах, где располагаются брейкпоинты вставить wait
    И усё


  19. Божечки кошечки. Да это же попытка #1000001 по созданию ОС для OpenComputers.
     

    1. Можете провести для меня эксперимент: "На сколько медленее работают N процессов на нескольких OC компах, чем на одном?"
      Просто у меня такое ощущение, что все компы в opencomputers исполняются в одном процессе
    2. Если вдруг будете пилить не забудьте сделать shared memory и system signals (SIGKILL, SIGINT, SIGSEGV и тп)
    3. КОД:
      supercomputer = require('supercomputer')
      Process = supercomputer.Process
      Pool = supercomputer.Pool
      Manager = supercomputer.Manager
      
      function handle(arg1, arg2, argN):
          variable = Process.share("variable", {1, 2, 3})
          sleep(5)
          lock = variable.get_lock()
          lock.close()
          variable.value = {1, 2, 8, 9}
          variable.value[3] = 12
          lock.open()
          sleep(3)
          lock = variable.get_lock()
          lock.close()
          variable.value[1] = 10
          variable.value[2] = 3
          lock.open()
          sleep(100)
          print(variable.value)
      end
      
      function mapper(datum)
          print(datum)
          return datum * 2
      end
      
      function main()
          manager = Manager()
      
          process = Process("process_1", handle, arg1, arg2, argN)
          process.start()
      
          variable = manager.get_shared(process, "variable")
          for i = 1, 10, 1
              print(i, variable.value)
              sleep(1)
      
          lock = variable.get_lock()
          lock.close()
          pool = Pool(10)
          variable.value = pool.map(variable.value, mapper, arg1, arg2, argN)
          lock.open()
          process.join()
      end
      
      main()
      
    4. ВЫВОД:
      1    1, 2, 3
      2    1, 2, 3
      3    1, 2, 3
      4    1, 2, 3
      5    1, 2, 3
      6    1, 2, 3
      7    1, 2, 12, 9
      8    1, 2, 12, 9
      9    10, 3, 12, 9
      10   10, 3, 12, 9
      3
      9
      10
      12
      20, 6, 24, 18
    • Нравится 1
×
×
  • Создать...