Compare commits
No commits in common. 'lab2' and 'lab2.1' have entirely different histories.
@ -1,88 +1,4 @@
|
|||||||
# Lab 2
|
# Lab 2
|
||||||
|
|
||||||
|
> "И тут я обнаружил что случайно сделал 3-5 задачи в 1-2"
|
||||||
## Диаграмма классов:
|
|
||||||
|
|
||||||
```mermaid
|
|
||||||
classDiagram
|
|
||||||
class BinarySearchTree {
|
|
||||||
- root : Node
|
|
||||||
+ add(student : Student) : void
|
|
||||||
+ each(&block) : void
|
|
||||||
- insert(node : Node, student : Student) : Node
|
|
||||||
- in_order_traversal(node : Node, &block) : void
|
|
||||||
}
|
|
||||||
|
|
||||||
class Node {
|
|
||||||
- student : Student
|
|
||||||
- left : Node
|
|
||||||
- right : Node
|
|
||||||
+ Node(student : Student)
|
|
||||||
}
|
|
||||||
|
|
||||||
class Person {
|
|
||||||
- id : String
|
|
||||||
- git : String
|
|
||||||
- phone : String?
|
|
||||||
- telegram : String?
|
|
||||||
- email : String?
|
|
||||||
+ Person(id : String, git : String, phone: String, telegram: String, email: String)
|
|
||||||
+ phone=(String) : Boolean
|
|
||||||
+ telegram=(String) : Boolean
|
|
||||||
+ email=(String) : Boolean
|
|
||||||
+ surname_initials() : NotImplementedError
|
|
||||||
+ valid_phone_number() : Boolean <<class>>
|
|
||||||
+ valid_telegram() : Boolean <<class>>
|
|
||||||
+ valid_email() : Boolean <<class>>
|
|
||||||
+ git_present() : Boolean
|
|
||||||
+ contact_present() : Boolean
|
|
||||||
+ get_first_contact() : String
|
|
||||||
+ git=(git : String) : void
|
|
||||||
+ validate_id(id: String) : void <<class>>
|
|
||||||
+ validate_git(git : String) : void <<class>>
|
|
||||||
- valid_git?(git : String) : Boolean
|
|
||||||
- valid_id?(id : String) : Boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
class StudentRepository {
|
|
||||||
+ read_from_txt(file_path : String) : List~Student~ <<class>>
|
|
||||||
+ write_to_txt(file_path : String, students : List~Student~) <<class>>
|
|
||||||
}
|
|
||||||
|
|
||||||
class StudentShort {
|
|
||||||
- surname_initials : String
|
|
||||||
+ get_surname_initials() : String
|
|
||||||
+ StudentShort(id : String, surname_initials : String, phone: String, telegram: String, email: String)
|
|
||||||
+ from_student(student : Student) : StudentShort <<class>>
|
|
||||||
+ from_string(id : String, info_string : String) : StudentShort <<class>>
|
|
||||||
+ to_s() : String
|
|
||||||
- parse_contact_string(contact_string: String) : Array<String> <<class>>
|
|
||||||
}
|
|
||||||
|
|
||||||
class Student {
|
|
||||||
- surname : String
|
|
||||||
- name : String
|
|
||||||
- patronymic : String
|
|
||||||
- birth_date : Date
|
|
||||||
- const NAME_REGEX : String
|
|
||||||
+ Student(id : String, git : String, phone: String, telegram: String, email: String, surname : String, name : String, patronymic : String, birth_date : Date)
|
|
||||||
+ from_string(student_string : String) : Student <<class>>
|
|
||||||
+ surname_initials() : String
|
|
||||||
+ to_s() : String
|
|
||||||
+ get_info() : String
|
|
||||||
+ surname=(surname : String)
|
|
||||||
+ name=(name : String)
|
|
||||||
+ patronymic=(patronymic : String)
|
|
||||||
+ birth_date=(birthdate : String)
|
|
||||||
+ valid_name?(name : String) : Boolean <<class>>
|
|
||||||
- name_initial(name : String) : String
|
|
||||||
- patronymic(patronymic : String) : String
|
|
||||||
}
|
|
||||||
|
|
||||||
BinarySearchTree o-- Node
|
|
||||||
Node o-- Student
|
|
||||||
Person <|-- Student
|
|
||||||
Person <|-- StudentShort
|
|
||||||
Student <.. StudentRepository
|
|
||||||
```
|
|
||||||
|
|
||||||
|
@ -1,46 +0,0 @@
|
|||||||
class BinarySearchTree
|
|
||||||
include Enumerable
|
|
||||||
|
|
||||||
class Node
|
|
||||||
attr_accessor :student, :left, :right
|
|
||||||
|
|
||||||
def initialize(student)
|
|
||||||
@student = student
|
|
||||||
@left = nil
|
|
||||||
@right = nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def initialize
|
|
||||||
@root = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
def add(student)
|
|
||||||
@root = insert(@root, student)
|
|
||||||
end
|
|
||||||
|
|
||||||
def each(&block)
|
|
||||||
in_order_traversal(@root, &block)
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def insert(node, student)
|
|
||||||
return Node.new(student) if node.nil?
|
|
||||||
|
|
||||||
if student.birth_date < node.student.birth_date
|
|
||||||
node.left = insert(node.left, student)
|
|
||||||
else
|
|
||||||
node.right = insert(node.right, student)
|
|
||||||
end
|
|
||||||
node
|
|
||||||
end
|
|
||||||
|
|
||||||
def in_order_traversal(node, &block)
|
|
||||||
return if node.nil?
|
|
||||||
|
|
||||||
in_order_traversal(node.left, &block)
|
|
||||||
yield node.student
|
|
||||||
in_order_traversal(node.right, &block)
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,85 +0,0 @@
|
|||||||
class Person
|
|
||||||
attr_reader :id, :git, :phone, :telegram, :email
|
|
||||||
|
|
||||||
def initialize(id:, git: nil, phone: nil, telegram: nil, email: nil)
|
|
||||||
self.class.validate_id(id)
|
|
||||||
self.phone = phone
|
|
||||||
self.telegram = telegram
|
|
||||||
self.email = email
|
|
||||||
raise ArgumentError, "Необходимо указать хотя бы один контакт (телефон, Telegram или email)" unless contact_present?
|
|
||||||
|
|
||||||
@id = id
|
|
||||||
@git = git
|
|
||||||
end
|
|
||||||
|
|
||||||
def surname_initials
|
|
||||||
raise NotImplementedError, "#{self.class} must implement the 'surname_initials' method"
|
|
||||||
end
|
|
||||||
|
|
||||||
def git_present?
|
|
||||||
!@git.nil? && !@git.empty?
|
|
||||||
end
|
|
||||||
|
|
||||||
def contact_present?
|
|
||||||
@phone || @telegram || @email
|
|
||||||
end
|
|
||||||
|
|
||||||
def get_first_contact
|
|
||||||
[@phone, @telegram, @email].compact.first
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.valid_phone_number?(phone)
|
|
||||||
/\A\+?[0-9]{9,15}\z/.match?(phone)
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.valid_telegram?(telegram)
|
|
||||||
/\A@[A-Za-z0-9_]{5,32}\z/.match?(telegram)
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.valid_email?(email)
|
|
||||||
/\A[^@\s]+@[^@\s]+\.[^@\s]+\z/.match?(email)
|
|
||||||
end
|
|
||||||
|
|
||||||
def phone=(phone)
|
|
||||||
if phone && !self.class.valid_phone_number?(phone)
|
|
||||||
raise ArgumentError, "Недопустимый номер телефона: #{phone}"
|
|
||||||
end
|
|
||||||
@phone = phone
|
|
||||||
end
|
|
||||||
|
|
||||||
def telegram=(telegram)
|
|
||||||
if telegram && !self.class.valid_telegram?(telegram)
|
|
||||||
raise ArgumentError, "Некорректный Telegram: #{telegram}"
|
|
||||||
end
|
|
||||||
@telegram = telegram
|
|
||||||
end
|
|
||||||
|
|
||||||
def email=(email)
|
|
||||||
if email && !self.class.valid_email?(email)
|
|
||||||
raise ArgumentError, "Некорректный email: #{email}"
|
|
||||||
end
|
|
||||||
@email = email
|
|
||||||
end
|
|
||||||
|
|
||||||
def git=(git)
|
|
||||||
self.class.validate_git(git)
|
|
||||||
@git = git
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.validate_id(id)
|
|
||||||
raise ArgumentError, 'ID is required and must be a non-empty string' unless valid_id?(id)
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.validate_git(git)
|
|
||||||
raise ArgumentError, 'Git link is required' if git.nil? || git.strip.empty?
|
|
||||||
raise ArgumentError, 'Invalid Git link format' unless valid_git?(git)
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.valid_git?(git)
|
|
||||||
/\Ahttps:\/\/github\.com\/[A-Za-z0-9_\-]+\z/.match?(git)
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.valid_id?(id)
|
|
||||||
id.is_a?(String) && !id.strip.empty?
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,39 +0,0 @@
|
|||||||
require_relative 'student'
|
|
||||||
|
|
||||||
class StudentRepository
|
|
||||||
def self.read_from_txt(file_path)
|
|
||||||
raise IOError, "File does not exist: #{file_path}" unless File.exist?(file_path)
|
|
||||||
|
|
||||||
students = []
|
|
||||||
|
|
||||||
File.foreach(file_path) do |line|
|
|
||||||
line.strip!
|
|
||||||
next if line.empty?
|
|
||||||
|
|
||||||
begin
|
|
||||||
student = Student.from_string(line)
|
|
||||||
students << student
|
|
||||||
rescue ArgumentError => e
|
|
||||||
puts "Error processing line: '#{line}'. Reason: #{e.message}"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
students
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.write_to_txt(file_path, students)
|
|
||||||
unless students.is_a?(Array) && students.all? { |s| s.is_a?(Student) }
|
|
||||||
raise ArgumentError, 'Expected an array of Student objects'
|
|
||||||
end
|
|
||||||
|
|
||||||
File.open(file_path, 'w') do |file|
|
|
||||||
students.each do |student|
|
|
||||||
file.puts student.to_s
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
puts "Data successfully written to #{file_path}"
|
|
||||||
rescue IOError => e
|
|
||||||
puts "An error occurred while writing to the file: #{e.message}"
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,59 +0,0 @@
|
|||||||
require_relative 'person'
|
|
||||||
|
|
||||||
class StudentShort < Person
|
|
||||||
attr_reader :surname_initials
|
|
||||||
|
|
||||||
def initialize(id:, surname_initials:, phone: nil, telegram: nil, email: nil)
|
|
||||||
super(id: id, phone: phone, telegram: telegram, email: email)
|
|
||||||
@surname_initials = surname_initials
|
|
||||||
freeze
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.from_student(student)
|
|
||||||
new(
|
|
||||||
id: student.id,
|
|
||||||
surname_initials: student.surname_initials,
|
|
||||||
phone: student.phone,
|
|
||||||
telegram: student.telegram,
|
|
||||||
email: student.email
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.from_string(id, info_string)
|
|
||||||
parts = info_string.split(',').map(&:strip)
|
|
||||||
raise ArgumentError, 'Invalid info string format' if parts.size < 2
|
|
||||||
|
|
||||||
surname_initials = parts[0]
|
|
||||||
contact_string = parts[1].split(': ', 2).last.strip
|
|
||||||
|
|
||||||
phone, telegram, email = parse_contact_string(contact_string)
|
|
||||||
|
|
||||||
new(
|
|
||||||
id: id,
|
|
||||||
surname_initials: surname_initials,
|
|
||||||
phone: phone,
|
|
||||||
telegram: telegram,
|
|
||||||
email: email
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
def to_s
|
|
||||||
contact_info = get_first_contact()
|
|
||||||
"#{@surname_initials}, Contact: #{contact_info}"
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def self.parse_contact_string(contact_string)
|
|
||||||
case contact_string
|
|
||||||
when /\APhone: (.+)\z/i
|
|
||||||
[Regexp.last_match(1).strip, nil, nil]
|
|
||||||
when /\ATelegram: (.+)\z/i
|
|
||||||
[nil, Regexp.last_match(1).strip, nil]
|
|
||||||
when /\AEmail: (.+)\z/i
|
|
||||||
[nil, nil, Regexp.last_match(1).strip]
|
|
||||||
else
|
|
||||||
raise ArgumentError, "Invalid contact string format: #{contact_string}"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,3 +0,0 @@
|
|||||||
Иванов Иван Иванович | ID: 1 | Phone: +12345678901 | Telegram: @ivanov_user | Email: ivanov@example.com | Git: https://github.com/ivanov
|
|
||||||
Петров Петр Петрович | ID: 2 | Phone: +98765432101 | Telegram: @petrov_user | Email: petrov@example.com | Git: https://github.com/petrov
|
|
||||||
Сидоров Сидор Сидорович | ID: 3 | Phone: +56789012345 | Telegram: @sidorov_user | Email: sidorov@example.com | Git: https://github.com/sidorov
|
|
Loading…
Reference in new issue