Added missing files and removed unnessesary ones

This commit is contained in:
StNicolay 2023-07-16 16:44:42 +03:00
parent c3fa5367c3
commit 199dd693e4
41 changed files with 1442 additions and 50 deletions

View File

@ -1,50 +0,0 @@
{
"files.associations": {
"algorithm": "cpp",
"iostream": "cpp",
"numeric": "cpp",
"array": "cpp",
"atomic": "cpp",
"bit": "cpp",
"*.tcc": "cpp",
"cctype": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"compare": "cpp",
"concepts": "cpp",
"cstdarg": "cpp",
"cstddef": "cpp",
"cstdint": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"cwchar": "cpp",
"cwctype": "cpp",
"deque": "cpp",
"string": "cpp",
"unordered_map": "cpp",
"vector": "cpp",
"exception": "cpp",
"functional": "cpp",
"iterator": "cpp",
"memory": "cpp",
"memory_resource": "cpp",
"random": "cpp",
"string_view": "cpp",
"system_error": "cpp",
"tuple": "cpp",
"type_traits": "cpp",
"utility": "cpp",
"initializer_list": "cpp",
"iosfwd": "cpp",
"istream": "cpp",
"limits": "cpp",
"new": "cpp",
"numbers": "cpp",
"ostream": "cpp",
"stdexcept": "cpp",
"streambuf": "cpp",
"typeinfo": "cpp",
"ctime": "cpp",
"cstring": "cpp"
}
}

View File

@ -545,3 +545,243 @@ void boo(int* ptr) {
## Структуры ## Структуры
> Структура - тип данных, позоляющий объединить несколько переменных в одной еденице. > Структура - тип данных, позоляющий объединить несколько переменных в одной еденице.
```C++
#include <iostream>
struct Employee {
short id;
int age;
double salary;
};
Employee john = {5, 20, 30.0};
std::cout << john.id << ' ' << john.age << ' ' << john.salary << '\n';
```
## Перечисления
> Перечисление - это пользовательский тип данных, который представляет собой набор именованных констант, которым присваиваются целочисленные значения. Весит как *int*
```C++
#include <iostream>
enum Weekday {
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday,
Sunday,
};
enum Weekday2 {
Monday = 1,
Tuesday = 2,
Wednesday = 3,
Thursday = 4,
Friday = 5,
Saturday = 6,
Sunday = 7,
};
Weekday today = Saturday;
```
Weekday полностью аналогичен Weekday2
## Объединение
> Объединение - это пользовательский тип данных, позволяющий хранить различные типы данных в одной области памяти. Объединение занимает память, достаточную для хранения переменной имеющий самый большой размер.
```C++
union MyUnion{
int intValue;
char charValue;
};
MyUnion val = 65;
int a = val.intValue; // 65
char b = val.charValue; // 'A'
```
## Передача значений в функцию (Подробнее)
* Передача по значению (создаётся копия, может быть медленно, используется для примитивов)
```C++
void increment(int a) {
a++;
}
int a = 5;
increment(&a); // a остаётся 5
```
* Передача по ссылке (копия не создаётся, используется для больших значений / структур, аналогична передаче по значению, но синтаксис проще)
```C++
void increment(int& a) {
a++;
}
int a = 5;
increment(a); // a становится 6
```
* Передача по указателю (копия не создаётся, используется в основном для массивов)
```C++
void increment(int* a) {
(*a)++;
}
int a = 5;
increment(&a); // a тоже становится 6
```
## Классы
> Классы - шаблон или описание, определяющее структуру поведения объектов.
> Объект - экземляр класса
```С++
class ClassName{
// Поля и методы класса
};
```
> Поля класса - переменные, котроые представляют состояие объетогв класса
> Методы класа - функции, которые определяют поведение объектов класса
```С++
ClassName objectName; // создание объекта класса просто
ClassName objectName = new ClassName(); //создание объекта класса сложно
delete objectName;
```
## Пример
```С++
#include <iostream>
#include <string>
class Person{
public:
std::string name;
int age;
void displayInfo(){
std::count << "Name: " << name << ", Age: " << age << '\n';
}
}
int main(){
Person person1;
person1.name = "Alice";
person1.age = 25;
person1.displayInfo();
Person* person2 = new Person();
person2 -> name = "Bob";
person2 -> age = 30;
person2 -> displayInfo();
delete person2;
return 0;
}
```
> Пользовательский тип данных
### Модификаторы доступа
* public - доступно всем (по умолчанию в struct)
* private - доступно только внутри класса (по умолчанию в class)
* protected - достпуно внутри класса и наследникам
### Конструктор и деструктор
> Конструктор - функция, которая вызывается при инициализации класса (может быть несколько)
> Деструктор - функция, которая вызывается при уничтожении объекта
```C++
#include <iostream>
class MyClass {
public:
MyClass() {
std::cout << "Constructed\n";
}
MyClass(int val) {
std::cout << "Constucted" << val << '\n';f
}
~MyClass() {
std::cout << "Destroyed\n";
}
};
```
### this
> this - указатель на объект вызвовший метод
```C++
#include <string>
class Foo{
public:
Person(std::string val) {
this->name = val;
}
};
```
## ООП
> Инкапсуляция - данные класса скрыты от прямого доступа и манипулиций извне класса
> Наследование - создаёт классы-потомки
> Полимарфизм - разные классы используют один и тот же интерфейс
```C++
#include <iostream>
class Figure {
public:
virtual void draw() {
std::cout << "Draw figure\n";
}
};
class Circe: public Figure {
public:
void draw() override {
std::cout << "Draw circle\n";
}
};
class Rectangle: public Figure {
public:
void draw() override {
std::cout << "Draw rectangle\n";
}
};
int main() {
Figure* figure = new Figure();
Figure* circle = new Circle():
Figure* rectangle = new Rectangle();
figure->draw();
circle->draw();
rectangle->draw();
delete figure;
delete circle;
delete rectangle;
}
```

BIN
C++/a.out

Binary file not shown.

16
C++/lesson6/task1.cpp Normal file
View File

@ -0,0 +1,16 @@
#include <iostream>
#include <string>
class Person {
private:
std::string name;
public:
Person(const std::string& name) {
this->name = name;
}
void printName() {
std::cout << this->name << '\n';
}
};

47
C++/lesson6/task2.cpp Normal file
View File

@ -0,0 +1,47 @@
#include <iostream>
#include <string>
class Student {
std::string name;
int age;
double average_grade;
public:
Student(std::string name, int age, double average) {
this->name = name;
this->age = age;
this->average_grade = average;
}
std::string& get_name() {
return name;
}
int get_age() {
return age;
}
double get_average_grade() {
return average_grade;
}
void status() {
if (average_grade >= 4 && average_grade < 5) {
std::cout << "Student is хорошист" << '\n';
} else if (average_grade = 5) {
std::cout << "Student is отличник" << '\n';
} else if (average_grade < 3) {
std::cout << "Student is двоечник" << '\n';
}
}
};
int main() {
Student student1("George", 19, 3.5);
Student student2("Paul", 14, 4.8);
Student student3("Vasyok", 17, 5);
student1.status();
student2.status();
student3.status();
}

40
C++/lesson6/task3.cpp Normal file
View File

@ -0,0 +1,40 @@
#include <iostream>
struct Account {
int number;
int money;
int percentage;
public:
Account(int number, int money, int percentage) {
this->number = number;
this->money = money;
this->percentage = percentage;
}
void refill(int amount) {
money += amount;
}
void withdraw(int amount) {
money -= amount;
}
void PrintInformation() {
std::cout << number << ' ' << money << ' ' << percentage << '\n';
}
};
int main() {
Account* account1 = new Account(21213, 500, 15);
account1->PrintInformation();
account1->refill(200);
account1->withdraw(50);
account1->PrintInformation();
Account* account2 = new Account(1934, 800, 10);
account2->PrintInformation();
account2->refill(150);
account2->withdraw(23);
account2->PrintInformation();
}

37
Python/clock/main.py Executable file
View File

@ -0,0 +1,37 @@
import sys
from time import strftime
from PyQt6.QtCore import QTimer
from PyQt6.QtWidgets import QApplication, QLCDNumber, QVBoxLayout, QWidget
class Window(QWidget):
def __init__(self):
super().__init__()
self.setGeometry(100, 100, 800, 400)
self.setWindowTitle("Clock")
vbox = QVBoxLayout()
self.timer = QTimer()
self.timer.timeout.connect(self.update_clock)
self.timer.start(200)
self.lcd = QLCDNumber()
vbox.addWidget(self.lcd)
self.setLayout(vbox)
def update_clock(self) -> None:
time_ = strftime("%H:%M:%S")
self.lcd.setDigitCount(8)
self.lcd.display(time_)
def main():
app = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec())
if __name__ == "__main__":
main()

BIN
Python/pyqt6_4/cat1.jpg Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 347 KiB

BIN
Python/pyqt6_4/cat2.jpg Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

21
Python/pyqt6_4/snippets/1.py Executable file
View File

@ -0,0 +1,21 @@
import sys
from PyQt6.QtWidgets import QApplication, QWidget
class Window(QWidget):
def __init__(self) -> None:
super().__init__()
self.setGeometry(*(500,) * 4)
self.setWindowTitle("Окно")
def main() -> None:
app = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec())
if __name__ == "__main__":
main()

61
Python/pyqt6_4/snippets/10.py Executable file
View File

@ -0,0 +1,61 @@
import sys
from PyQt6.QtWidgets import (
QApplication,
QWidget,
QHBoxLayout,
QSpinBox,
QLabel,
QLineEdit,
)
from PyQt6.QtGui import QFont
class Window(QWidget):
def __init__(self) -> None:
super().__init__()
self.setGeometry(*(500,) * 4)
self.setWindowTitle("Окно")
self.price = 300
self.amount = 0
hbox = QHBoxLayout()
self.line_edit = QLineEdit(str(self.price))
self.line_edit.setFont(QFont("Times", 14))
self.spin_box = QSpinBox()
self.spin_box.valueChanged.connect(self.handle_spin_box)
self.result = QLabel(str(self.total))
hbox.addWidget(self.line_edit)
hbox.addWidget(self.spin_box)
hbox.addWidget(self.result)
self.setLayout(hbox)
def handle_spin_box(self) -> None:
try:
self.price = int(self.line_edit.text())
except ValueError:
return
self.amount = self.spin_box.value()
self.result.setText(str(self.total))
@property
def total(self) -> int:
return self.amount * self.price
def handle_line_edit(self) -> None:
pass
def main() -> None:
app = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec())
if __name__ == "__main__":
main()

31
Python/pyqt6_4/snippets/2.py Executable file
View File

@ -0,0 +1,31 @@
import sys
from PyQt6.QtWidgets import QApplication, QWidget, QLabel
from PyQt6.QtGui import QPixmap
class Window(QWidget):
def __init__(self) -> None:
super().__init__()
self.setGeometry(*(500,) * 4)
self.setWindowTitle("Окно")
label = QLabel(self)
label.setText("Текст")
label.move(300, 300)
pixmap = QPixmap()
lable_pic = QLabel(self)
lable_pic.setPicture(pixmap)
lable_pic.move(200, 200)
def main() -> None:
app = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec())
if __name__ == "__main__":
main()

31
Python/pyqt6_4/snippets/3.py Executable file
View File

@ -0,0 +1,31 @@
import sys
from PyQt6.QtWidgets import QApplication, QWidget, QPushButton
from PyQt6.QtCore import QSize
from PyQt6.QtGui import QFont, QIcon
class Window(QWidget):
def __init__(self) -> None:
super().__init__()
self.setGeometry(*(500,) * 4)
self.setWindowTitle("Окно")
self.create_button()
def create_button(self) -> None:
btn = QPushButton("Click", self)
btn.setGeometry(*(100,) * 4)
btn.setFont(QFont("Times", 14, QFont.Weight.ExtraBold))
btn.setIcon(QIcon("cat1.jpg"))
btn.setIconSize(QSize(50, 50))
def main() -> None:
app = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec())
if __name__ == "__main__":
main()

27
Python/pyqt6_4/snippets/4.py Executable file
View File

@ -0,0 +1,27 @@
import sys
from PyQt6.QtGui import QFont
from PyQt6.QtWidgets import QApplication, QLineEdit, QWidget
class Window(QWidget):
def __init__(self) -> None:
super().__init__()
self.setGeometry(*(500,) * 4)
self.setWindowTitle("Окно")
line_edit = QLineEdit(self)
line_edit.setFont(QFont("Times", 14))
line_edit.setPlaceholderText("Enter your password")
line_edit.setEchoMode(QLineEdit.EchoMode.Password)
def main() -> None:
app = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec())
if __name__ == "__main__":
main()

32
Python/pyqt6_4/snippets/5.py Executable file
View File

@ -0,0 +1,32 @@
import sys
from PyQt6.QtWidgets import QApplication, QWidget, QPushButton, QHBoxLayout
class Window(QWidget):
def __init__(self) -> None:
super().__init__()
self.setGeometry(*(500,) * 4)
self.setWindowTitle("Окно")
btn1 = QPushButton("One")
btn2 = QPushButton("Two")
btn3 = QPushButton("Three")
layout = QHBoxLayout()
layout.addWidget(btn1)
layout.addWidget(btn2)
layout.addWidget(btn3)
self.setLayout(layout)
def main() -> None:
app = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec())
if __name__ == "__main__":
main()

32
Python/pyqt6_4/snippets/6.py Executable file
View File

@ -0,0 +1,32 @@
import sys
from PyQt6.QtWidgets import QApplication, QWidget, QPushButton, QVBoxLayout
class Window(QWidget):
def __init__(self) -> None:
super().__init__()
self.setGeometry(*(500,) * 4)
self.setWindowTitle("Окно")
btn1 = QPushButton("One")
btn2 = QPushButton("Two")
btn3 = QPushButton("Three")
layout = QVBoxLayout()
layout.addWidget(btn1)
layout.addWidget(btn2)
layout.addWidget(btn3)
self.setLayout(layout)
def main() -> None:
app = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec())
if __name__ == "__main__":
main()

63
Python/pyqt6_4/snippets/7.py Executable file
View File

@ -0,0 +1,63 @@
import sys
from PyQt6.QtCore import QSize
from PyQt6.QtGui import QIcon
from PyQt6.QtWidgets import (
QApplication,
QHBoxLayout,
QLabel,
QRadioButton,
QVBoxLayout,
QWidget,
)
ICON_SIZE = 100
class Window(QWidget):
def __init__(self) -> None:
super().__init__()
self.setGeometry(200, 200, 400, 300)
self.setWindowTitle("Окно")
self.create_radio()
def create_radio(self) -> None:
hbox = QHBoxLayout()
rad1 = QRadioButton("Cat 1")
rad1.setIcon(QIcon("cat1.jpg"))
rad1.setIconSize(QSize(ICON_SIZE, ICON_SIZE))
rad1.toggled.connect(self.radio_selected)
rad2 = QRadioButton("Cat 2")
rad2.setIcon(QIcon("cat2.jpg"))
rad2.setIconSize(QSize(ICON_SIZE, ICON_SIZE))
rad2.toggled.connect(self.radio_selected)
hbox.addWidget(rad1)
hbox.addWidget(rad2)
vbox = QVBoxLayout()
self.label = QLabel("")
vbox.addWidget(self.label)
vbox.addLayout(hbox)
self.setLayout(vbox)
def radio_selected(self) -> None:
radio_btn = self.sender()
if radio_btn.isEnabled():
self.label.setText(f"You have chosen {radio_btn.text().lower()}")
def main() -> None:
app = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec())
if __name__ == "__main__":
main()

68
Python/pyqt6_4/snippets/8.py Executable file
View File

@ -0,0 +1,68 @@
import sys
from PyQt6.QtCore import QSize
from PyQt6.QtGui import QIcon
from PyQt6.QtWidgets import (
QApplication,
QCheckBox,
QHBoxLayout,
QLabel,
QVBoxLayout,
QWidget,
)
ICON_SIZE = 100
class Window(QWidget):
def __init__(self) -> None:
super().__init__()
self.setGeometry(200, 200, 400, 300)
self.setWindowTitle("Окно")
self.create_radio()
def create_radio(self) -> None:
hbox = QHBoxLayout()
self.check1 = QCheckBox("Cat 1")
self.check1.setIcon(QIcon("cat1.jpg"))
self.check1.setIconSize(QSize(ICON_SIZE, ICON_SIZE))
self.check1.toggled.connect(self.radio_selected)
self.check2 = QCheckBox("Cat 2")
self.check2.setIcon(QIcon("cat2.jpg"))
self.check2.setIconSize(QSize(ICON_SIZE, ICON_SIZE))
self.check2.toggled.connect(self.radio_selected)
hbox.addWidget(self.check1)
hbox.addWidget(self.check2)
vbox = QVBoxLayout()
self.label = QLabel("You haven't chosen anything")
vbox.addWidget(self.label)
vbox.addLayout(hbox)
self.setLayout(vbox)
def radio_selected(self) -> None:
text = "You have chosen "
if self.check1.isChecked():
text += self.check1.text().lower() + ", "
if self.check2.isChecked():
text += self.check2.text().lower()
if not any((self.check1.isChecked(), self.check2.isChecked())):
text = "You haven't chosen anything"
text = text.removesuffix(", ")
self.label.setText(text)
def main() -> None:
app = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec())
if __name__ == "__main__":
main()

70
Python/pyqt6_4/snippets/9.py Executable file
View File

@ -0,0 +1,70 @@
import sys
from enum import StrEnum
from PyQt6.QtGui import QFont
from PyQt6.QtWidgets import (
QApplication,
QComboBox,
QHBoxLayout,
QLabel,
QVBoxLayout,
QWidget,
)
class CatType(StrEnum):
ORANGE = "one orange brain cell"
VOID = "void"
DUST = "dust kitty"
class Window(QWidget):
def __init__(self) -> None:
super().__init__()
self.setGeometry(*(500,) * 4)
self.setWindowTitle("Окно")
self.current_type = CatType.ORANGE
self.create_combo()
def create_combo(self) -> None:
hbox = QHBoxLayout()
label = QLabel("Select cat type:")
label.setFont(QFont("Times", 15))
self.combo = QComboBox(self)
for cat_type in CatType:
self.combo.addItem(cat_type.capitalize())
self.combo.currentTextChanged.connect(self.combo_changed)
hbox.addWidget(label)
hbox.addWidget(self.combo)
vbox = QVBoxLayout()
self.label_result = QLabel(
f"Current cat: {self.current_type.capitalize()}",
)
self.label_result.setFont(QFont("Times", 15))
vbox = QVBoxLayout()
vbox.addWidget(self.label_result)
vbox.addLayout(hbox)
self.setLayout(vbox)
def combo_changed(self) -> None:
self.current_type = CatType(self.combo.currentText().lower())
self.label_result.setText(
f"Current cat: {self.current_type.capitalize()}",
)
def main() -> None:
app = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec())
if __name__ == "__main__":
main()

0
Python/pyqt6_4/task1.py Executable file
View File

0
Python/pyqt6_4/test.py Executable file
View File

BIN
Python/soper/flag.jpg Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

207
Python/soper/soper.py Executable file
View File

@ -0,0 +1,207 @@
import sys
from dataclasses import dataclass
from enum import StrEnum, auto
from random import sample
from typing import Any, Callable, Iterator, Self
from PyQt6 import QtGui
from PyQt6.QtCore import QSize, Qt, QTimer
from PyQt6.QtGui import QIcon
from PyQt6.QtWidgets import (
QApplication,
QHBoxLayout,
QLabel,
QLCDNumber,
QMessageBox,
QPushButton,
QVBoxLayout,
QWidget,
)
@dataclass(slots=True, frozen=True)
class Cords:
x: int
y: int
class ButtonType(StrEnum):
EMPTY = auto()
BOMB = auto()
NUMBER = auto()
class Button(QPushButton):
def __init__(
self,
cords: Cords,
handler1: Callable[[Self, bool], Any],
handler2: Callable[[Self], Any],
) -> None:
super().__init__()
self.setFixedSize(50, 50)
self.type = ButtonType.EMPTY
self.number = 0
self.cords = cords
self.marked: bool = False
self.revealed: bool = False
self.left_handler = handler1
self.right_handler = handler2
def reveal(self) -> Iterator[Cords]:
self.revealed = True
self.setStyleSheet("background-color: grey")
if self.type is ButtonType.NUMBER:
self.setText(str(self.number))
def mousePressEvent(self, e: QtGui.QMouseEvent) -> None:
if e.button() is Qt.MouseButton.LeftButton:
self.left_handler(self, True)
elif e.button() is Qt.MouseButton.RightButton:
self.right_handler(self)
def get_neighbors(self) -> Iterator[Cords]:
for x in range(self.cords.x - 1, self.cords.x + 2):
for y in range(self.cords.y - 1, self.cords.y + 2):
if x < 0 or x >= 10:
continue
if y < 0 or y >= 10:
continue
if Cords(x, y) == self.cords:
continue
yield Cords(x, y)
def update_texture(self) -> None:
if self.marked:
self.setIcon(QIcon("flag.jpg"))
self.setIconSize(QSize(50, 50))
else:
self.setIcon(QIcon())
# TODO: remove
if self.type is ButtonType.BOMB:
self.setStyleSheet("background-color: red")
class Window(QWidget):
def __init__(self) -> None:
super().__init__()
self.setGeometry(0, 0, 500, 500)
self.seconds = 0
self.revealed_buttons: set[Cords] = set()
self.timer = QTimer()
self.timer.timeout.connect(self.show_time)
self.timer.setInterval(1000)
self.timer.start()
self.bomb_amount = 10
self.flags_amount = 0
self.setWindowTitle("Окно")
self.create_buttons()
self.select_bombs()
def create_buttons(self) -> None:
vbox = QVBoxLayout()
hbox = QHBoxLayout()
self.counter = QLabel(f"{self.flags_amount}/{self.bomb_amount}")
finish_button = QPushButton()
finish_button.setText("FINISH")
finish_button.clicked.connect(self.finish)
self.time = QLCDNumber()
self.time.setDigitCount(5)
self.time.display("00:00")
hbox.addWidget(self.counter)
hbox.addWidget(finish_button)
hbox.addWidget(self.time)
vbox.addLayout(hbox)
self.buttons: list[list[Button]] = []
for x in range(10):
hbox = QHBoxLayout()
row = []
for y in range(10):
button = Button(
Cords(x, y),
self.button_clicked,
self.set_flag,
)
row.append(button)
hbox.addWidget(button)
self.buttons.append(row)
vbox.addLayout(hbox)
self.setLayout(vbox)
def select_bombs(self) -> None:
buttons = [j for i in self.buttons for j in i]
bombs = sample(buttons, self.bomb_amount)
for bomb in bombs:
bomb.type = ButtonType.BOMB
# TODO: remove
bomb.setStyleSheet("background-color: red")
for bomb in bombs:
for cords in bomb.get_neighbors():
button = self.buttons[cords.x][cords.y]
if button.type is ButtonType.BOMB:
continue
button.type = ButtonType.NUMBER
button.number += 1
def button_clicked(self, button: Button, user: bool) -> None:
if button.cords in self.revealed_buttons:
return
self.revealed_buttons.add(button.cords)
if button.type is ButtonType.BOMB:
if user:
QMessageBox.warning(self, "You lost", "You lost")
self.close()
return
button.reveal()
if button.type is ButtonType.NUMBER:
return
for cords in button.get_neighbors():
neighbor = self.buttons[cords.x][cords.y]
self.button_clicked(neighbor, False)
def set_flag(self, button: Button) -> None:
if button.revealed:
return
was_marked = button.marked
button.marked = not was_marked
button.update_texture()
if was_marked:
self.flags_amount -= 1
else:
self.flags_amount += 1
self.counter.setText(f"{self.flags_amount}/{self.bomb_amount}")
def finish(self) -> None:
buttons = [j for i in self.buttons for j in i]
bomb = ButtonType.BOMB
if not all(button.marked for button in buttons if button.type is bomb):
QMessageBox.warning(self, "You lost", "You lost")
self.close()
return
QMessageBox.information(self, "You won", "You won")
self.close()
def show_time(self) -> None:
self.seconds += 1
minutes, seconds = divmod(self.seconds, 60)
self.time.display(f"{minutes:0>2}:{seconds:0>2}")
if minutes >= 5:
QMessageBox.warning(self, "You lost", "You lost")
self.close()
return
def main() -> None:
app = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec())
if __name__ == "__main__":
main()

419
Python/sql/main.py Executable file
View File

@ -0,0 +1,419 @@
from __future__ import annotations
import os
import sys
from typing import Optional
import psycopg2
from psycopg2 import extensions
from PyQt6.QtWidgets import (
QApplication,
QHBoxLayout,
QLabel,
QLineEdit,
QMessageBox,
QPushButton,
QTableWidget,
QTableWidgetItem,
QVBoxLayout,
QWidget,
)
from cryptography.hazmat.primitives.kdf.scrypt import Scrypt
from cryptography.exceptions import InvalidKey
def get_kdf(salt: bytes) -> Scrypt:
return Scrypt(salt, length=128, n=2**14, r=8, p=1)
def encrypt(password: str) -> bytes:
salt = os.urandom(64)
return (salt, get_kdf(salt).derive(password.encode("UTF-8")))
def check_password(password: str, salt: bytes, expected: bytes) -> bool:
try:
get_kdf(salt).verify(password.encode("UTF-8"), expected)
except InvalidKey:
return False
else:
return True
Student = tuple[int, str, str, str]
HOST = "127.0.0.1"
USER = "tester"
PASSWORD = "example123!"
PORT = 5432
DATABASE = "testing"
class Connection:
connection: Optional[extensions.connection] = None
@classmethod
def get(cls) -> extensions.connection:
if cls.connection is not None:
return cls.connection
try:
cls.connection = psycopg2.connect(
host=HOST, user=USER, password=PASSWORD, database=DATABASE
)
cls.connection.autocommit = True
except Exception as e:
print(type(e))
raise
return cls.connection
@classmethod
def close(cls) -> None:
if cls.connection is not None:
cls.connection.close()
cls.connection = None
@classmethod
def get_all_data(cls) -> list[Student]:
with cls.get().cursor() as cursor:
cursor.execute("SELECT * FROM students ORDER BY id")
return cursor.fetchall()
@classmethod
def get_user(cls, login: str) -> Optional[tuple[bytes, bytes]]:
with cls.get().cursor() as cursor:
cursor.execute(
"SELECT salt, password, admin FROM users WHERE login = %s",
(login,),
)
result = cursor.fetchone()
if result is None:
return None
return (bytes(result[0]), bytes(result[1]), result[2])
def prepare_database() -> None:
with Connection.get().cursor() as cursor:
cursor.execute("DROP TABLE IF EXISTS students")
cursor.execute(
"CREATE TABLE students("
"id INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,"
"surname VARCHAR(255),"
"name VARCHAR(255),"
"group_ VARCHAR(255))"
)
cursor.execute("DROP TABLE IF EXISTS users")
cursor.execute(
"CREATE TABLE users("
"id INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,"
"login VARCHAR(255),"
"salt BYTEA,"
"password BYTEA,"
"admin BOOLEAN)"
)
def add_test_data() -> None:
with Connection.get().cursor() as cursor:
cursor.execute(
"INSERT INTO STUDENTS(name, surname, group_) VALUES "
"('Nick', 'Stepanov', 'programmer'),"
"('Maxim', 'Yes', 'programmer')"
)
admin_creds = encrypt("admin")
user_creds = encrypt("example123!")
cursor.execute(
"INSERT INTO users(login, salt, password, admin) VALUES "
"('admin', %s, %s, true),"
"('user', %s, %s, false)",
(*admin_creds, *user_creds),
)
class Window(QWidget):
def __init__(self, is_admin: bool):
super().__init__()
self.is_admin = is_admin
self.setGeometry(200, 200, 700, 400)
self.setWindowTitle("SQL Test")
self.vbox = QVBoxLayout()
self.setLayout(self.vbox)
self.need_clean = []
self.update()
def update(self, data: Optional[list[Student]] = None):
self.clean_widgets()
if data is None:
data = Connection.get_all_data()
hbox_buttons = QHBoxLayout()
but1 = QPushButton("Create")
but1.clicked.connect(self.button_create_handler)
but2 = QPushButton("Edit")
but2.clicked.connect(self.button_edit_handler)
but3 = QPushButton("Remove")
but3.clicked.connect(self.button_remove_handler)
but4 = QPushButton("Find")
but4.clicked.connect(self.button_find_handler)
hbox_buttons.addWidget(but1)
hbox_buttons.addWidget(but2)
hbox_buttons.addWidget(but3)
hbox_buttons.addWidget(but4)
self.add_widget_to_need_clean(but1, but2, but3, but4)
hbox_id = QHBoxLayout()
label_id = QLabel("ID")
self.text_id = QLineEdit()
hbox_id.addWidget(label_id)
hbox_id.addWidget(self.text_id)
self.add_widget_to_need_clean(hbox_id, label_id, self.text_id)
hbox_surname = QHBoxLayout()
label_surname = QLabel("Surname")
self.text_surname = QLineEdit()
hbox_surname.addWidget(label_surname)
hbox_surname.addWidget(self.text_surname)
self.add_widget_to_need_clean(
hbox_surname,
label_surname,
self.text_surname,
)
hbox_name = QHBoxLayout()
label_name = QLabel("Name")
self.text_name = QLineEdit()
hbox_name.addWidget(label_name)
hbox_name.addWidget(self.text_name)
self.add_widget_to_need_clean(hbox_name, label_name, self.text_name)
hbox_group = QHBoxLayout()
label_group = QLabel("Group")
self.text_group = QLineEdit()
hbox_group.addWidget(label_group)
hbox_group.addWidget(self.text_group)
self.add_widget_to_need_clean(hbox_group, label_group, self.text_group)
hbox_table = QHBoxLayout()
table = self.form_table(data)
hbox_table.addWidget(table)
self.add_widget_to_need_clean(table)
self.vbox.addLayout(hbox_id)
self.vbox.addLayout(hbox_surname)
self.vbox.addLayout(hbox_name)
self.vbox.addLayout(hbox_group)
self.vbox.addLayout(hbox_buttons)
self.vbox.addLayout(hbox_table)
def add_widget_to_need_clean(self, *args):
for el in args:
self.need_clean.append(el)
def clean_widgets(self):
if self.need_clean:
for widget in self.need_clean:
widget.deleteLater()
self.need_clean.clear()
@staticmethod
def form_table(data: list[Student]) -> QTableWidget:
table = QTableWidget()
table.setRowCount(10)
table.setColumnCount(4)
table.setHorizontalHeaderLabels(("ID", "Surname", "Name", "Group"))
for i, row in enumerate(data):
for j, column in enumerate(map(str, row)):
table.setItem(i, j, QTableWidgetItem(column))
return table
def button_edit_handler(self):
if not self.is_admin:
return QMessageBox().warning(
self, "Rights", "You have to be an admin to do that"
)
with Connection.get().cursor() as cursor:
cursor.execute("SELECT * FROM students;")
students = cursor.fetchall()
indexes = []
for student in students:
indexes.append(str(student[0]))
if self.text_id.text() in indexes:
commands = []
if self.text_surname.text() != "":
commands.append(
"UPDATE students SET surname = '"
+ self.text_surname.text()
+ "' "
+ "WHERE id = "
+ self.text_id.text()
+ ";"
)
if self.text_name.text() != "":
commands.append(
"UPDATE students SET name = '"
+ self.text_name.text()
+ "' "
+ "WHERE id = "
+ self.text_id.text()
+ ";"
)
if self.text_group.text() != "":
commands.append(
"UPDATE students SET gr = '"
+ self.text_group.text()
+ "' "
+ "WHERE id = "
+ self.text_id.text()
+ ";"
)
with Connection.get().cursor() as cursor:
for command in commands:
cursor.execute(command)
QMessageBox.information(self, "Info", "Data changed")
else:
QMessageBox.warning(self, "Error", "Data not changed")
self.update()
def button_create_handler(self):
if not self.is_admin:
return QMessageBox().warning(
self, "Rights", "You have to be an admin to do that"
)
name = self.text_name.text()
surname = self.text_surname.text()
group = self.text_group.text()
if not all((surname, name, group)):
QMessageBox.warning(self, "Invalid id", "Invalid id")
return
with Connection.get().cursor() as cursor:
cursor.execute(
"INSERT INTO students(name, surname, group_) VALUES (%s, %s, %s)", # noqa
(name, surname, group),
)
self.update()
def button_remove_handler(self) -> None:
if not self.is_admin:
return QMessageBox().warning(
self, "Rights", "You have to be an admin to do that"
)
try:
id = int(self.text_id.text())
except ValueError:
QMessageBox.warning(self, "Invalid ID", "Invalid ID")
return
with Connection.get().cursor() as cursor:
cursor.execute("DELETE FROM students WHERE id = %s", (id,))
self.update()
def button_find_handler(self) -> None:
id = self.text_id.text()
name = self.text_name.text()
surname = self.text_surname.text()
group = self.text_group.text()
filters = []
params = []
if id:
if not id.isnumeric():
QMessageBox.warning(self, "Invalid id", "Invalid id")
return
filters.append("id = %s")
params.append(id)
if name:
filters.append("LOWER(name) ~ %s")
params.append(name.lower())
if surname:
filters.append("LOWER(surname) ~ %s")
params.append(surname.lower())
if group:
filters.append("LOWER(group_) ~ %s")
params.append(group.lower())
with Connection.get().cursor() as cursor:
if not params:
filters = ""
else:
filters = f" WHERE {' AND '.join(filters)}"
query = f"SELECT * FROM students{filters} ORDER BY id"
cursor.execute(query, params)
data = cursor.fetchall()
self.update(data)
class WindowPW(QWidget):
def __init__(self) -> None:
super().__init__()
self.loged_in = False
self.is_admin = False
self.setGeometry(200, 200, 250, 150)
self.setWindowTitle("Login")
label = QLabel("Name", self)
label.move(10, 10)
self.line_login = QLineEdit(self)
self.line_login.move(100, 10)
label_pw = QLabel("password", self)
label_pw.move(10, 50)
self.line_pw = QLineEdit(self)
self.line_pw.move(100, 50)
register_but = QPushButton("Register", self)
register_but.move(25, 100)
register_but.clicked.connect(self.register_handler)
but = QPushButton("OK", self)
but.clicked.connect(self.but_handler)
but.move(100, 100)
def but_handler(self) -> None:
login = self.line_login.text().strip()
password = self.line_pw.text().strip()
user = Connection.get_user(login)
if user is None:
self.close()
return QMessageBox.warning(self, "Bye!", "Wrong creds")
salt, expected, admin = Connection.get_user(login)
if check_password(password, salt, expected):
self.loged_in = True
self.is_admin = admin
else:
QMessageBox.warning(self, "Bye!", "Wrong creds")
self.close()
def register_handler(self) -> None:
login = self.line_login.text().strip()
password = self.line_pw.text().strip()
if not (login and password):
return QMessageBox().warning(
self, "Wrong creds", "You must input both login and password"
)
with Connection.get().cursor() as cursor:
cursor.execute(
"SELECT true FROM users WHERE login = %s LIMIT 1",
(login,),
)
if cursor.fetchone() is not None:
return QMessageBox().warning(
self, "Wrong creds", "Login already exists"
)
cursor.execute(
"INSERT INTO users(login, salt, password) VALUES (%s, %s, %s)",
(login, *encrypt(password)),
)
self.loged_in = True
self.close()
def main() -> None:
prepare_database()
add_test_data()
app = QApplication(sys.argv)
window = WindowPW()
window.show()
result = app.exec()
if not window.loged_in:
sys.exit(result)
window = Window(window.is_admin)
window.show()
sys.exit(app.exec())
if __name__ == "__main__":
main()