require_relative 'person' class Student < Person attr_accessor :surname, :name, :patronymic def initialize(args = {}) super(args) @surname = args.fetch(:surname) { raise ArgumentError, "Surname is required" } raise ArgumentError, "Invalid surname format: #{@surname}" unless self.class.valid_name?(@surname) @name = args.fetch(:name) { raise ArgumentError, "Name is required" } raise ArgumentError, "Invalid name format: #{@name}" unless self.class.valid_name?(@name) @patronymic = args.fetch(:patronymic) { raise ArgumentError, "Patronymic is required" } raise ArgumentError, "Invalid patronymic format: #{@patronymic}" unless self.class.valid_name?(@patronymic) set_contacts( phone: args[:phone], telegram: args[:telegram], email: args[:email] ) end def self.from_string(student_string) raise ArgumentError, "Input string cannot be nil or empty" if student_string.nil? || student_string.strip.empty? parts = student_string.split('|').map(&:strip) # Ожидается формат: "Фамилия Имя Отчество | ID: X | Phone: ... | Telegram: ... | Email: ... | Git: ..." # Проверяем, что частей как минимум 6: ФИО, ID, Phone, Telegram, Email, Git unless parts.size == 6 raise ArgumentError, "Expected 6 parts separated by '|', got #{parts.size} in '#{student_string}'" end fio_part = parts[0] raise ArgumentError, "FIO part is empty" if fio_part.nil? || fio_part.strip.empty? fio_elements = fio_part.split(' ') raise ArgumentError, "Expected Surname Name Patronymic in '#{fio_part}'" unless fio_elements.size == 3 surname, name, patronymic = fio_elements id_part = parts[1] raise ArgumentError, "ID part is empty or invalid" if id_part.nil? || !id_part.include?('ID:') id_str = id_part.split(': ').last raise ArgumentError, "ID value is missing in '#{id_part}'" if id_str.nil? || id_str.strip.empty? id = id_str.to_i raise ArgumentError, "ID must be a valid integer: '#{id_str}'" if id == 0 && id_str != "0" phone_part = parts[2] raise ArgumentError, "Phone part is invalid or missing" if phone_part.nil? || !phone_part.include?('Phone:') phone = phone_part.split(': ').last phone = nil if phone == 'N/A' telegram_part = parts[3] raise ArgumentError, "Telegram part is invalid or missing" if telegram_part.nil? || !telegram_part.include?('Telegram:') telegram = telegram_part.split(': ').last telegram = nil if telegram == 'N/A' email_part = parts[4] raise ArgumentError, "Email part is invalid or missing" if email_part.nil? || !email_part.include?('Email:') email = email_part.split(': ').last email = nil if email == 'N/A' git_part = parts[5] raise ArgumentError, "Git part is invalid or missing" if git_part.nil? || !git_part.include?('Git:') git = git_part.split(': ').last git = nil if git == 'N/A' new( surname: surname, name: name, patronymic: patronymic, id: id, phone: phone, telegram: telegram, email: email, git: git ) end def self.read_from_txt(file_path) raise IOError, "File path is invalid or 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 = from_string(line) students << student rescue ArgumentError => e puts "Error processing line: '#{line}'. Reason: #{e.message}" rescue StandardError => e puts "An unexpected error occurred while processing line: '#{line}'. Reason: #{e.message}" end end students end def self.write_to_txt(file_path, students) raise ArgumentError, "Expected an array of Student objects" unless students.is_a?(Array) && students.all? { |s| s.is_a?(Student) } 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}" rescue StandardError => e puts "An unexpected error occurred while writing to the file: #{e.message}" end def surname_and_initials "#{@surname} #{name[0]}.#{patronymic[0]}." end def to_s "#{@surname} #{@name} #{@patronymic} | ID: #{@id || 'N/A'} | " \ "Phone: #{@phone || 'N/A'} | Telegram: #{@telegram || 'N/A'} | " \ "Email: #{@email || 'N/A'} | Git: #{@git || 'N/A'}" end def get_info "#{surname_and_initials}, Git: #{git_info}, Contact: #{contact_info}" end end