Compare commits

...

45 Commits
lab2.1 ... lab2

Author SHA1 Message Date
Artem-Darius Weber 2126888d8a refactor: implement surname_initials method and update references for consistency
4 days ago
Artem-Darius Weber bffdd2f072 refactor: rename name_initials to surname_initials for consistency
4 days ago
Artem-Darius Weber bb2280d48e refactor: rename surname_initials to name_initials for consistency
4 days ago
Artem-Darius Weber 6bf0914189 refactor: update method visibility in class diagram for clarity
4 days ago
Artem-Darius Weber 002212a6f8 refactor: remove validate_contact method from class diagram for clarity
4 days ago
Artem-Darius Weber 6da1bacfd5 refactor: rename contact_info method to get_first_contact for clarity
4 days ago
Artem-Darius Weber 2932741c0e refactor: update class method signatures to remove 'self' and improve readability
4 days ago
Artem-Darius Weber e327cf09f6 refactor: freeze StudentShort instance after initialization
4 days ago
Artem-Darius Weber 5ec7fb96d1 refactor: consolidate contact attributes into Person and Student classes, removing Contact class
7 days ago
Artem-Darius Weber 223a312037 refactor: remove git attribute from Person and StudentShort classes and simplify contact information handling
7 days ago
Artem-Darius Weber 582c184acb refactor: remove Contact class and integrate contact attributes directly into Person and Student classes
7 days ago
Artem-Darius Weber a78cbb3a67 refactor: update class method signatures and improve initialization in Person and Student classes
1 week ago
Artem-Darius Weber 09c78690f1 refactor: update Person class to use class methods for validation and simplify initialization
1 week ago
Artem-Darius Weber 8679f3744a refactor: move contact attribute validation to setter methods in Contact class
1 week ago
Artem-Darius Weber f8a012e9dd refactor: update validation methods in Contact and Student classes to use class methods
1 week ago
Artem-Darius Weber 3fade34834 refactor: remove git validation from initializer and add setter method in Person class
1 week ago
Artem-Darius Weber a9717abae8 refactor: simplify Student initialization and move name validation to class method
1 week ago
Artem-Darius Weber d5f67c2de0 refactor: convert instance validation methods to class methods in Contact class
1 week ago
Artem-Darius Weber 0b3d315370 refactor: rename info method to get_single_contact in Contact class and update references
1 week ago
Artem-Darius Weber 4e91bae07c chore: remove unnecessary comment from Person class
1 week ago
Artem-Darius Weber 7e7110f01e feat: add validation setters in Contact class and refine Person and StudentShort classes
1 week ago
Artem-Darius Weber 1f750e1334 feat: add BinarySearchTree and enhance Student class with birth_date and validation methods
2 weeks ago
Artem-Darius Weber dbd1dfe45d feat: add BinarySearchTree class and integrate birth_date handling in Student class LAB 3 TASK 4
2 weeks ago
Artem-Darius Weber b9ffeb8d0d chore: remove unnecessary comment from README.md
4 weeks ago
Artem-Darius Weber 5f3c510253 feat: enhance validation in Person class and add present? method in Contact class
4 weeks ago
Artem-Darius Weber 3490c8f0f7 feat: refactor Contact class initialization and validation methods for better error handling
4 weeks ago
Artem-Darius Weber d0279bf2e9 feat: update valid_phone_number method to allow phone numbers with 9 to 15 digits
4 weeks ago
Artem-Darius Weber c222d7bdd0 Merge branch 'restore-lab2' into lab2
4 weeks ago
Artem-Darius Weber be544ae87d feat: implement testing functions for Contact, Person, Student, and StudentShort classes; add sample student data
4 weeks ago
Artem-Darius Weber 80e86e0f99 feat: update class diagram in README.md to include Contact class and its relationships
4 weeks ago
Artem-Darius Weber a622813621 feat: add new_from_info method to Contact class for creating instances from formatted strings
4 weeks ago
Artem-Darius Weber d392be8d5d refactor: update Student class initialization and validation; add StudentRepository for file operations
4 weeks ago
Artem-Darius Weber 72fa11dbfa refactor: enhance StudentShort initialization and add from_student method
4 weeks ago
Artem-Darius Weber 5cd9be99e3 refactor: simplify Person class initialization and validation logic
4 weeks ago
Artem-Darius Weber 5550b9563b feat: add Contact class with validation for phone, telegram, and email
4 weeks ago
Artem-Darius Weber aae53e8617 docs: add class diagram to README.md for Person, Student, and StudentShort classes
1 month ago
Artem-Darius Weber a9b27d76c5 feat: enhance Student and Person classes with contact information validation
1 month ago
Artem-Darius Weber cbd9231784 docs: add class diagram to README.md for Person, Student, and StudentShort classes
1 month ago
Artem-Darius Weber e79d92eed3 refactor: streamline initialization and validation in Person class
1 month ago
Artem-Darius Weber dc752cdf43 feat: add write_txt method to Student class
4 months ago
Artem-Darius Weber acf69c4385 feat: Add read_from_txt method to Student class
4 months ago
Artem-Darius Weber d387e12d7d ref: Extract common functionality into Person superclass
4 months ago
Artem-Darius Weber 68ca94d4e9 feat: add StudentShort class with immutable fields and constructors
4 months ago
Artem-Darius Weber 611c712b8a feat: add `get_info` method and protected access to key student info
4 months ago
Artem-Darius Weber 8858731565 feat: add constructor for Student class to parse object from string representation
4 months ago

BIN
.DS_Store vendored

Binary file not shown.

@ -1,4 +1,88 @@
# 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
```

@ -0,0 +1,46 @@
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,33 +1,92 @@
require 'date'
require_relative 'person'
require_relative 'student'
require_relative 'student_short'
require_relative 'student_repository'
require_relative 'binary_search_tree'
begin
student1 = Student.new(
surname: 'Алексеевич',
name: 'Артем-Дариус',
patronymic: 'Вебер',
id: 1,
git: 'https://git.djft.ru'
)
def test_classes
person = Person.new(id: '1', git: 'https://github.com/example', phone: '+798912465', telegram: '@example_user', email: 'test@example.com')
puts "Person Contact Info: #{person.get_first_contact}"
student1.set_contacts(
phone: '+79891242223',
telegram: '@alstroemeria22',
email: 'no-replay@djft.ru'
student = Student.new(
id: '2',
git: 'https://github.com/student_example',
surname: 'Иванов',
name: 'Иван',
patronymic: 'Иванович',
birth_date: Date.new(2000, 5, 15),
phone: '+79891234567',
telegram: '@student_ivan',
email: 'ivanov@example.com'
)
puts "Student Full Info: #{student.to_s}"
puts "Student Initials: #{student.surname_initials}"
puts "Student Contact Info: #{student.get_first_contact}"
student_short = StudentShort.from_student(student)
puts "Student Short Info: #{student_short.to_s}"
file_path = 'students.txt'
students = StudentRepository.read_from_txt(file_path)
puts "Read Students from File:"
students.each { |s| puts s.to_s }
output_path = 'output_students.txt'
StudentRepository.write_to_txt(output_path, students)
puts "Students written to file: #{output_path}"
end
def test_parsing
student_string = 'Иванов Иван Иванович | ID: 3 | Phone: +79876543210 | Telegram: @ivan_user | Email: ivan@example.com | Git: https://github.com/ivanov | Birth Date: 2001-01-01'
student = Student.from_string(student_string)
puts "Parsed Student: #{student.to_s}"
short_string = 'Иванов И.И., Contact: Phone: +79876543210'
student_short = StudentShort.from_string('4', short_string)
puts "Parsed StudentShort: #{student_short.to_s}"
end
def test_binary_search_tree
bst = BinarySearchTree.new
student1 = Student.new(
id: '1',
git: 'https://github.com/student1',
surname: 'Смирнов',
name: 'Алексей',
patronymic: 'Иванович',
birth_date: Date.new(1999, 2, 15),
phone: '+123456789',
telegram: '@student1',
email: 'student1@example.com'
)
student2 = Student.new(
surname: 'Норакет',
name: 'Норакет',
patronymic: 'Фамилия'
id: '2',
git: 'https://github.com/student2',
surname: 'Иванов',
name: 'Иван',
patronymic: 'Сергеевич',
birth_date: Date.new(2001, 5, 10),
phone: '+987654321',
telegram: '@student2',
email: 'student2@example.com'
)
student2.set_contacts(
phone: '+70000000000'
)
bst.add(student1)
bst.add(student2)
puts "Students in BST (sorted by birth_date):"
bst.each { |student| puts student.to_s }
end
if __FILE__ == $0
puts "=== Testing Classes ==="
test_classes
puts "\n=== Testing Parsing ==="
test_parsing
puts student1
puts '-' * 40
puts student2
rescue ArgumentError => e
puts "Ошибка: #{e.message}"
puts "\n=== Testing Binary Search Tree ==="
test_binary_search_tree
end

@ -0,0 +1,85 @@
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,86 +1,103 @@
class Student
attr_accessor :id, :surname, :name, :patronymic, :git
require_relative 'person'
def self.valid_phone_number?(phone)
phone.match?(/\A\+?[0-9]{10,15}\z/)
end
class Student < Person
attr_accessor :surname, :name, :patronymic, :birth_date
def self.valid_name?(name)
name.match?(/\A[А-Яа-яЁёA-Za-z\-]+\z/)
end
private
def self.valid_telegram?(telegram)
telegram.nil? || telegram.match?(/\A@[A-Za-z0-9_]{5,32}\z/)
end
NAME_REGEX = /\A[А-Яа-яЁёA-Za-z\-]+\z/
def self.valid_email?(email)
email.nil? || email.match?(/\A[^@\s]+@[^@\s]+\.[^@\s]+\z/)
end
public
def self.valid_git?(git)
git.nil? || git.match?(/\Ahttps:\/\/github\.com\/[A-Za-z0-9_\-]+\z/)
def initialize(id:, git:, surname:, name:, patronymic:, birth_date:, phone: nil, telegram: nil, email: nil)
super(id: id, git: git, phone: phone, telegram: telegram, email: email)
self.surname = surname
self.name = name
self.patronymic = patronymic
self.birth_date = birth_date
end
def initialize(args = {})
@surname = args.fetch(:surname)
raise ArgumentError, "Invalid surname format: #{@surname}" unless Student.valid_name?(@surname)
@name = args.fetch(:name)
raise ArgumentError, "Invalid name format: #{@name}" unless Student.valid_name?(@name)
@patronymic = args.fetch(:patronymic)
raise ArgumentError, "Invalid patronymic format: #{@patronymic}" unless Student.valid_name?(@patronymic)
@id = args[:id] || nil
set_contacts(
phone: args[:phone],
telegram: args[:telegram],
email: args[:email]
def self.from_string(student_string)
parts = student_string.split('|').map(&:strip)
raise ArgumentError, 'Invalid student string format' if parts.size < 7
name_parts = parts[0].split(' ')
raise ArgumentError, 'Invalid name format' if name_parts.size != 3
surname, name, patronymic = name_parts
id = parts[1].split(': ').last
phone = parts[2].split(': ').last
telegram = parts[3].split(': ').last
email = parts[4].split(': ').last
git = parts[5].split(': ').last
birth_date = Date.parse(parts[6].split(': ').last)
new(
id: id,
git: git,
surname: surname,
name: name,
patronymic: patronymic,
birth_date: birth_date,
phone: phone,
telegram: telegram,
email: email
)
end
@git = args[:git]
raise ArgumentError, "Invalid git format: #{@git}" unless Student.valid_git?(@git)
def surname_initials
"#{@surname} #{name_initial(@name)}.#{patronymic_initial(@patronymic)}."
end
validate
def to_s
"#{@surname} #{@name} #{@patronymic} | ID: #{@id} | " \
"Phone: #{@phone || 'N/A'} | Telegram: #{@telegram || 'N/A'} | " \
"Email: #{@email || 'N/A'} | Git: #{@git} | Birth Date: #{@birth_date}"
end
def set_contacts(phone: nil, telegram: nil, email: nil)
@phone = phone
raise ArgumentError, "Invalid phone number format: #{@phone}" if @phone && !Student.valid_phone_number?(@phone)
def get_info
"#{surname_initials}, Git: #{@git}, Contact: #{get_first_contact}, Birth Date: #{@birth_date}"
end
@telegram = telegram
raise ArgumentError, "Invalid telegram format: #{@telegram}" if @telegram && !Student.valid_telegram?(@telegram)
def surname=(surname)
raise ArgumentError, 'Surname is required' if surname.nil? || surname.strip.empty?
raise ArgumentError, "Invalid surname format: #{surname}" unless self.class.valid_name?(surname)
@email = email
raise ArgumentError, "Invalid email format: #{@email}" if @email && !Student.valid_email?(@email)
@surname = surname
end
def git_present?
!@git.nil? && !@git.empty?
def name=(name)
raise ArgumentError, 'Name is required' if name.nil? || name.strip.empty?
raise ArgumentError, "Invalid name format: #{name}" unless self.class.valid_name?(name)
@name = name
end
def contact_present?
!(@phone.nil? || @phone.empty?) || !(@telegram.nil? || @telegram.empty?) || !(@email.nil? || @email.empty?)
def patronymic=(patronymic)
raise ArgumentError, 'Patronymic is required' if patronymic.nil? || patronymic.strip.empty?
raise ArgumentError, "Invalid patronymic format: #{patronymic}" unless self.class.valid_name?(patronymic)
@patronymic = patronymic
end
def validate
raise ArgumentError, "Git link is required" unless git_present?
raise ArgumentError, "At least one contact (phone, telegram, or email) is required" unless contact_present?
def birth_date=(birth_date)
raise ArgumentError, 'Birth date is required' if birth_date.nil?
raise ArgumentError, "Invalid birth date: #{birth_date}" unless birth_date.is_a?(Date)
@birth_date = birth_date
end
def to_s
"Student: #{@surname} #{@name} #{@patronymic}\n" \
"ID: #{@id || 'N/A'}\n" \
"Phone: #{@phone || 'N/A'}\n" \
"Telegram: #{@telegram || 'N/A'}\n" \
"Email: #{@email || 'N/A'}\n" \
"Git: #{@git || 'N/A'}"
def self.valid_name?(name)
NAME_REGEX.match?(name)
end
private
attr_reader :phone, :telegram, :email
def name_initial(name)
name[0].upcase
end
attr_writer :phone, :telegram, :email
def patronymic_initial(patronymic)
patronymic[0].upcase
end
end

@ -0,0 +1,39 @@
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

@ -0,0 +1,59 @@
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

@ -0,0 +1,3 @@
Иванов Иван Иванович | 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…
Cancel
Save