Евгений Колесников 4 months ago
parent
commit
53af05ec59
6 changed files with 209 additions and 0 deletions
  1. 27 0
      articles/de2026_3_analysis.md
  2. 182 0
      articles/de2026_4_analisys.md
  3. BIN
      img/de26_m4_01.png
  4. BIN
      img/de26_m4_02.png
  5. BIN
      img/de26_m4_03.png
  6. BIN
      img/de26_m4_04.png

+ 27 - 0
articles/de2026_3_analysis.md

@@ -0,0 +1,27 @@
+# Разбор задания модуля 3
+
+## Создание SQL запроса
+
+>Создайте запрос, позволяющий вычислить полную стоимость заказа покупателя с учетом следующей информации:
+>
+>- количество продукции в заказе;
+>- стоимость всех материалов, использованных для производства данной продукции (учитывая норму расхода).
+
+На мой взгляд, при реальной работе, использовать сумму цен материалов как итог для заказа продуктов нельзя, так как в цене продажи кроме сырья должны учитываться аммортизация оборудования, фонд оплаты труда, НДС и маржа предприятия.
+
+А в задании нужно написать обычный запрос с JOIN-ами и группировкой. Ниже примерный шаблон запроса, так как базы у меня нет
+
+```sql
+SELECT
+    SUM(
+        pm.`Количество маетриала в товаре` * 
+        m.`Цена материала` *
+        op.`Количество продукта в заказе`
+    ) AS Price
+FROM `Order` o
+JOIN OrderProduct op ON o.id = op.OrderId
+JOIN Product p ON op.ProductId = p.id
+JOIN ProductMaterial pm ON p.ProductId = pm.ProductId
+JOIN Materual m ON m.id = pm.MaterialId
+GROUP BY o.id
+```

+ 182 - 0
articles/de2026_4_analisys.md

@@ -0,0 +1,182 @@
+# Разбор модуля 4 предварительного задания демо-экзамена 2026 года
+
+## Доработка структуры БД
+
+>Для выполнения задания рекомендуется создать в базе данных таблицу "Пользователи". Если такая таблица уже существует, необходимо внести некоторые изменения для реализации дальнейшего функционала приложения.
+
+Просто добавте таблицу с полями `login`, `password`, `role`, `enabled` и добавьте в нее пару записей с разными ролями (в этом модуле уже не оценивается ERD, поэтому делать таблицу ролей не обязательно)
+
+## Авторизация по логиину/паролю
+
+>Разработайте форму для авторизации зарегистрированных пользователей с ролями "Администратор" и "Пользователь". Форма должна содержать поля текстовые поля логин, пароль и кнопку "Войти". Поля "Логин" и "Пароль" должны быть обязательными для заполнения. При неверно введенных данных, пользователь должен получить сообщение об ошибке "Вы ввели неверный логин или пароль. Пожалуйста проверьте ещё раз введенные данные".
+>
+>После успешной авторизации пользователь должен получить сообщение "Вы успешно авторизовались".
+>
+>При аутентификации связка «логин/пароль» должна совпадать с одной из записей в таблице "Пользователи".
+
+Тут все просто: заполняем логин/пароль и ищем в БД НЕ ЗАБЛОКИРОВАННОГО (`enabled = 1`) пользователя с таким логином и паролем
+
+## Интерактивная капча
+
+>На страницу авторизации добавьте интерактивную капчу, в которой пользователю необходимо собрать исходное изображение из фрагментов.
+Метод сборки изображения может быть произвольным. После сборки изображения система проверяет правильность расположения фрагментов.
+>
+>Если пазл собран верно — пользователь проходит проверку и может авторизоваться.
+
+Мы в рамках лекций с картинками особенно не работали - закроем этот пробел.
+
+Что нам необходимо сделать:
+
+- вывести в окне 4 картинки в случайные кооринаты
+- реализовать перемещение картинок по окну
+- проверить правильно ли собран паззл
+
+### Вывод картинок
+
+1. Создайте в окне именованный элемент __Canvas__ (у меня тестовое приложение, в котором он занимает все содержимое окна, вы вписывайте в форму авторизации)
+
+    ```xml
+    <Grid>
+        <Canvas
+            Name="DragArena"/>
+    </Grid>
+    ```
+
+1. Создайте в проекте каталог __images__ и скопируйте в него части паззла
+
+    ![](../img/de26_m4_01.png)
+
+    Не забудьте каждое изображение включить в ресурсы
+
+    ![](../img/de26_m4_02.png)
+
+1. По идее картинки можно закинуть в канвас и руками, но я приведу программный способ:
+
+    В конструкторе окна добавьте следующий код
+
+    ```cs
+    // это стандартное содержимое конструктора
+    InitializeComponent();
+
+    // дальше добавляемый код
+
+    // создаем экземпляр генератора случайных чисел
+    var random = new Random();
+
+    for (int i = 1; i < 5; i++)
+    {
+        // создаем новую картинку
+        Image myImage = new Image();
+
+        // в качестве источника устанавливаем один из кусочков паззла
+        myImage.Source = new BitmapImage(
+            new Uri($"/images/{i}.png", UriKind.Relative)
+        );
+
+        // оригинальное изображение 700px, 
+        // это, на мой взгляд, многовато - задаем 
+        // альтернативный размер изображения
+        myImage.Width = 200;
+
+        // присваиваем обработчику клика левой кнопкой 
+        // делегат (функцию обработчки)
+        myImage.MouseLeftButtonDown += Image_MouseLeftButtonDown;
+
+        // задаем левую/верхнюю точку для изображения 
+        // случайным образом
+        // в параметрах метода Next минимальное и максимальное
+        // значение результата
+        Canvas.SetLeft(myImage, random.Next(0, 200));
+        Canvas.SetTop(myImage, random.Next(0, 200));
+
+        // добавляем созданное и настроенное 
+        // изображение на холст (Canvas)
+        // (DragArena - название холста)
+        DragArena.Children.Add(myImage);
+    }
+    ```
+
+    И в класс окна дописываем поля, обработчики клика и движения мыши
+
+    ```cs
+    private Image? draggingImage;
+
+    private void Image_MouseLeftButtonDown(
+        object sender, 
+        MouseButtonEventArgs e)
+    {
+        // на всякий случай проверяем, что кликнули по Image
+        if (e.Source is Image image)
+        {
+            // запоминаем элемент, который будем двигать
+            draggingImage = image;
+
+            // вычисляем и запоминаем текущую координату
+            relativeMousePos = e.GetPosition(draggingImage) - new Point();
+
+            // задаем делегаты для отслеживания движения
+            draggingImage.MouseMove += OnDragMove;
+            draggingImage.LostMouseCapture += OnLostCapture;
+            draggingImage.MouseUp += OnMouseUp;
+
+            Mouse.Capture(draggingImage);
+        }
+    }
+
+    // при движении мыши обновляем позицию активной картинки
+    void OnDragMove(object sender, MouseEventArgs e)
+    {
+        UpdatePosition(e);
+    }
+
+    void UpdatePosition(MouseEventArgs e)
+    {
+        var point = e.GetPosition(DragArena);
+        var newPos = point - relativeMousePos;
+        Canvas.SetLeft(draggingImage, newPos.X);
+        Canvas.SetTop(draggingImage, newPos.Y);
+    }
+
+    void OnMouseUp(object sender, MouseButtonEventArgs e)
+    {
+        FinishDrag(sender, e);
+        Mouse.Capture(null);
+    }
+
+    void OnLostCapture(object sender, MouseEventArgs e)
+    {
+        FinishDrag(sender, e);
+    }
+
+    // при отпускании мыши отписываемся от делегатов
+    void FinishDrag(object sender, MouseEventArgs e)
+    {
+        draggingImage.MouseMove -= OnDragMove;
+        draggingImage.LostMouseCapture -= OnLostCapture;
+        draggingImage.MouseUp -= OnMouseUp;
+        UpdatePosition(e);
+    }
+    ```
+
+Если все сделали правильно, то при зпуске приложения увидим что-то подобное:
+
+![](../img/de26_m4_03.png)
+
+Картинки перетаскиваютс мышкой и складываются в картинку
+
+![](../img/de26_m4_04.png)
+
+Код для проверки "собранности" паззла я не привожу, он примитивный - нужно сравнить координаты соседних кусочков паззла (для этого создать массив и записать созданные изображения в него), заложив допустимую дельту, чтобы не целиться с точностью до пикселя
+
+## Блокировка аккаунта
+
+>Если в течении 3-х раз подряд пазл собран не верно или не верно введен пароль, то учетная запись блокируется и при повторной авторизации должно появляться сообщение "Вы заблокированы. Обратитесь к администратору".
+
+Меняем в БД поле `enabled` на `0`
+
+## CRUD пользователей
+
+>На рабочем столе пользователя с ролью "Администратор" предусмотрите функционал для добавления новых пользователей, изменения данных текущих пользователей (включая снятие блокировки). При добавлении нового пользователя следует проверять его наличие в базе данных.
+В случае, если пользователь с указанным логином уже существует, должно выводиться соответствующее сообщение.
+
+Тут обычный список пользователей с возможностью содания, удаления и редактироания

BIN
img/de26_m4_01.png


BIN
img/de26_m4_02.png


BIN
img/de26_m4_03.png


BIN
img/de26_m4_04.png