student_list_yaml_gem 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 10576fb140bc58bc6b580ab3e74a37538d0bf6bf16b8f6eff774b1e2b5946767
4
+ data.tar.gz: '0779fdbb0450c06b19ec726740c233f39bca5962c5be946585edd2c6f4e13077'
5
+ SHA512:
6
+ metadata.gz: dc656e8a694d8e60a06e701cc90410188855d6eb2d2072e4d87ad0cf1b80edfd5b81f068524e68ff3f4f6f65af399227656fa71cadf4ad267ce9342ef377eec5
7
+ data.tar.gz: ec2395929753ec1fbf131a339e291e4760181dcd45f61fa7d15b8b7941124d8b8cdd1a2383b9f8482693d3554b4085f289d26bd61ea4f0f2d9d4ced576f9a046
data/lib/data_list.rb ADDED
@@ -0,0 +1,49 @@
1
+ require_relative 'data_table.rb'
2
+
3
+ class DataList
4
+ def initialize(array)
5
+ self.data = array
6
+ @selected = []
7
+ end
8
+
9
+ def data=(array)
10
+ @array = array.freeze
11
+ end
12
+
13
+ def select(index)
14
+ raise ArgumentError if index < 0 || index >= @array.length
15
+ @selected << index unless @selected.include?(index)
16
+ end
17
+
18
+ def get_selected
19
+ @selected.map { |i| @array[i].id }
20
+ end
21
+
22
+ def clear_selected
23
+ @selected.clear
24
+ end
25
+
26
+ def get_names
27
+ ["№ по порядку"] + get_custom_names
28
+ end
29
+
30
+ def get_data
31
+ rows = []
32
+ @array.each_with_index do |obj, index|
33
+ rows << [index + 1] + get_custom_row(obj)
34
+ end
35
+
36
+ DataTable.new(rows)
37
+ end
38
+
39
+ protected
40
+
41
+ def get_custom_names
42
+ raise NotImplementedError
43
+ end
44
+
45
+ def get_custom_row(obj)
46
+ raise NotImplementedError
47
+ end
48
+
49
+ end
@@ -0,0 +1,13 @@
1
+ require_relative 'data_list.rb'
2
+ require_relative 'student_short.rb'
3
+
4
+ class DataListStudentShort < DataList
5
+
6
+ def get_custom_names
7
+ ["ФИО", "Контакт", "Гит"]
8
+ end
9
+
10
+ def get_custom_row(student)
11
+ [student.last_name_initials, student.contact, student.git]
12
+ end
13
+ end
data/lib/data_table.rb ADDED
@@ -0,0 +1,22 @@
1
+ class DataTable
2
+ def initialize(rows)
3
+ @rows = rows.map { |x| x.freeze }
4
+ end
5
+
6
+ def get(row, col)
7
+ @rows[row][col]
8
+ end
9
+
10
+ def rows
11
+ @rows.length
12
+ end
13
+
14
+ def columns
15
+ return 0 if @rows.empty?
16
+ @rows[0].length
17
+ end
18
+
19
+ def to_s
20
+ @rows.to_s
21
+ end
22
+ end
data/lib/student.rb ADDED
@@ -0,0 +1,135 @@
1
+ require_relative 'super_student.rb'
2
+
3
+ class Student < SuperStudent
4
+ include Comparable
5
+
6
+ attr_reader :last_name, :first_name, :patronymic
7
+
8
+ def self.validated_attr_writer(attribute, validation_method)
9
+ define_method("#{attribute}=") do |value|
10
+ raise ArgumentError unless self.class.send(validation_method, value)
11
+ instance_variable_set("@#{attribute}", value)
12
+ end
13
+ end
14
+
15
+ validated_attr_writer :first_name, :valid_name?
16
+ validated_attr_writer :last_name, :valid_name?
17
+ validated_attr_writer :patronymic, :valid_name?
18
+ validated_attr_writer :git, :valid_git?
19
+
20
+ def <=>(other)
21
+ [first_name, last_name, patronymic || nil] <=> [other.first_name, other.last_name, other.patronymic || nil]
22
+ end
23
+
24
+ def initialize(last_name:, first_name:, id: nil, patronymic: nil, phone: nil, telegram: nil, email: nil, git: nil)
25
+
26
+ raise ArgumentError, "Неверный формат гита" unless self.class.valid_git?(git)
27
+ super(id: id, git: git)
28
+
29
+ self.last_name = last_name
30
+ self.first_name = first_name
31
+ self.patronymic = patronymic
32
+
33
+ self.contact = {telegram: telegram, email: email, phone: phone}
34
+
35
+ end
36
+
37
+ def ==(other)
38
+ self_data = self.to_hash
39
+ other_data = other.to_hash
40
+
41
+ [:telegram, :email, :phone, :git].each do |field|
42
+ self_value = self_data[field]
43
+ other_value = other_data[field]
44
+
45
+ return true if self_value && other_value && self_value == other_value
46
+ end
47
+
48
+ false
49
+ end
50
+
51
+ def to_hash
52
+ {
53
+ id: @id,
54
+ first_name: @first_name,
55
+ last_name: @last_name,
56
+ patronymic: @patronymic,
57
+ telegram: @telegram,
58
+ email: @email,
59
+ phone: @phone,
60
+ git: @git
61
+ }
62
+ end
63
+
64
+ def self.initialize_hash(id: nil, student_hash:)
65
+ new(
66
+ id: id,
67
+ last_name: student_hash[:last_name],
68
+ first_name: student_hash[:first_name],
69
+ patronymic: student_hash[:patronymic],
70
+ telegram: student_hash[:telegram],
71
+ email: student_hash[:email],
72
+ phone: student_hash[:phone],
73
+ git: student_hash[:git]
74
+ )
75
+ end
76
+
77
+ def contact
78
+ if @telegram && !@telegram.empty?
79
+ "telegram - #{@telegram}"
80
+ elsif @email && !@email.empty?
81
+ "email - #{@email}"
82
+ elsif @phone && !@phone.empty?
83
+ "phone - #{@phone}"
84
+ else
85
+ nil
86
+ end
87
+ end
88
+
89
+ def contact=(contacts)
90
+ contacts.each do |type, value|
91
+ validator = "valid_#{type}?".to_sym
92
+ raise ArgumentError, "Неверный формат #{type}" unless self.class.send(validator, value)
93
+ instance_variable_set("@#{type}", value)
94
+ end
95
+ end
96
+
97
+ def last_name_initials
98
+ initials = "#{last_name} #{first_name[0]}."
99
+ initials += " #{patronymic[0]}." if patronymic
100
+ initials
101
+ end
102
+
103
+ def to_s
104
+ info = []
105
+ info << "ID: #{@id}" if @id
106
+ info << "Фамилия: #{@last_name}"
107
+ info << "Имя: #{@first_name}"
108
+ info << "Отчество: #{@patronymic}" if @patronymic
109
+ info << "Телефон: #{@phone}" if @phone
110
+ info << "Телеграм: #{@telegram}" if @telegram
111
+ info << "Почта: #{@email}" if @email
112
+ info << "Гит: #{@git}" if @git
113
+ info.join("\n")
114
+ end
115
+
116
+ def self.valid_name?(name)
117
+ name.nil? || name.is_a?(String) && name.match?(/^([А-Я][а-я]+|[A-Z][a-z]+)$/)
118
+ end
119
+
120
+ def self.valid_phone?(phone)
121
+ phone.nil? || (phone.is_a?(String) && phone.match?(/^(\+7|8)?[\s\-\(]?(\d{3})[\s\-\)]?(\d{3})[\s\-]?(\d{2})[\s\-]?(\d{2})$/))
122
+ end
123
+
124
+ def self.valid_telegram?(telegram)
125
+ telegram.nil? || (telegram.is_a?(String) && telegram.match?(/^@[a-zA-Z0-9_]{5,32}$/))
126
+ end
127
+
128
+ def self.valid_email?(email)
129
+ email.nil? || (email.is_a?(String) && email.match?(/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/))
130
+ end
131
+
132
+ def self.valid_git?(git)
133
+ git.nil? || (git.is_a?(String) && git.match?(/^https:\/\/(github|gitlab)\.com\/[a-zA-Z0-9_-]+\/?$/))
134
+ end
135
+ end
@@ -0,0 +1,116 @@
1
+ require 'yaml'
2
+ require_relative 'student.rb'
3
+ require_relative 'data_list_student_short.rb'
4
+ require_relative 'unique_student_error.rb'
5
+
6
+ # Класс для работы со списком студентов, хранящимся в YAML-файле
7
+ class StudentListYAML
8
+
9
+ # Инициализация списка студентов
10
+ # @param file_path [String]
11
+ def initialize(file_path:, log_path: nil)
12
+ @file_path = file_path
13
+ @logger = log_path ? AppLogger.build(log_path) : nil
14
+ @students = read
15
+ end
16
+
17
+ # Чтение студентов из файла
18
+ # @return [Array<Student>] массив студентов
19
+ def read
20
+ @logger.debug('read yaml')
21
+
22
+ return [] unless File.exist?(@file_path)
23
+
24
+ data = YAML.load_file(@file_path)
25
+ return [] unless data.is_a?(Array)
26
+
27
+ data.map do |student_hash|
28
+ Student.initialize_hash(id: student_hash[:id], student_hash: student_hash)
29
+ end
30
+
31
+ rescue => e
32
+ @logger.error(e.message)
33
+ []
34
+ end
35
+
36
+ # Записывает данные студентов в YAML-файл
37
+ def write
38
+ students_hash = @students.map { |student| student.to_hash }
39
+ File.write(@file_path, students_hash.to_yaml)
40
+ end
41
+
42
+ # Получить студента по ID
43
+ # @param id [Integer]
44
+ # @return [Student, nil]
45
+ def get_student_by_id(id)
46
+ @logger.debug("get_student_by_id #{id}")
47
+ @students.find { |student| student.id = id }
48
+ rescue => e
49
+ @logger.error(e.message)
50
+ end
51
+
52
+ # Получить список студентов
53
+ # @param k [Integer] номер первого элемента
54
+ # @param n [Integer] количество элементов
55
+ # @return [DataList]
56
+ def get_k_n_student_short_list(k, n)
57
+ students = @students.slice(k - 1, n)
58
+ list = DataListStudentShort.new(students)
59
+ list.get_data
60
+ end
61
+
62
+ # Сортировка студентов по ФамилияИнициалы
63
+ def sort_by_name
64
+ @students.sort_by! { |student| student.last_name_initials }
65
+ end
66
+
67
+ # Добавление студента в список
68
+ # @param student [Student]
69
+ def add_student(student)
70
+ @logger.info("add_student #{student.short_info}")
71
+ new_id = @students.map(&:id).max.to_i + 1
72
+
73
+ new_student = Student.initialize_hash(id: new_id, student_hash: student.to_hash)
74
+ unique(new_student)
75
+
76
+ @students << new_student
77
+ rescue => e
78
+ @logger.error(e.message)
79
+ end
80
+
81
+ # Изменение студента по id
82
+ # @param id [Integer]
83
+ # @param new_student [Student]
84
+ def update_student(id:, new_student:)
85
+ @logger.info("update_student_id: #{id}")
86
+
87
+ index = @students.index { |student| student.id == id }
88
+ return unless index
89
+ unique(new_student)
90
+ @students[index] = new_student
91
+
92
+ rescue => e
93
+ @logger.error(e.message)
94
+ end
95
+
96
+ # Удаление студента по id
97
+ # param id [Integer]
98
+ def delete_student(id)
99
+ @logger.info("delete_student_id: #{id}")
100
+
101
+ @students.reject! { |s| s.id == id }
102
+
103
+ rescue => e
104
+ @logger.error(e.message)
105
+ end
106
+
107
+ private
108
+
109
+ # Проверка студентов на уникальность
110
+ def unique(new_student)
111
+ @students.each do |student|
112
+ raise UniqueStudentError, "Ошибка уникальности студента" if student == new_student
113
+ end
114
+ end
115
+
116
+ end
@@ -0,0 +1,25 @@
1
+ require_relative 'student.rb'
2
+ require_relative 'super_student.rb'
3
+
4
+
5
+ class StudentShort < SuperStudent
6
+
7
+ attr_reader :last_name_initials, :contact
8
+
9
+ def initialize(id:, last_name_initials:, contact: nil, git: nil)
10
+ super(id: id, git: git)
11
+ @last_name_initials = last_name_initials
12
+ @contact = contact
13
+ end
14
+
15
+ def self.from_student(student)
16
+ raise ArgumentError, "Отсутствует ID" unless student.id
17
+ new(
18
+ id: student.id,
19
+ last_name_initials: student.last_name_initials,
20
+ contact: student.contact,
21
+ git: student.git
22
+ )
23
+ end
24
+
25
+ end
@@ -0,0 +1,41 @@
1
+ class SuperStudent
2
+
3
+ attr_reader :id, :git
4
+
5
+ def initialize(id: nil, git: nil)
6
+ @id = id
7
+ @git = git
8
+ end
9
+
10
+ def short_info
11
+ info = []
12
+ info << "ID: #{id}" if id
13
+ info << "ФИО: #{last_name_initials}"
14
+ info << "Контакт: #{contact}" if contact
15
+ info << "Гит: #{git}" if git
16
+ info.join("\n")
17
+ end
18
+
19
+ def to_s
20
+ short_info
21
+ end
22
+
23
+ def has_git?
24
+ !@git.nil? && !@git.empty?
25
+ end
26
+
27
+ def has_contact?
28
+ !contact.nil? && !contact.empty?
29
+ end
30
+
31
+ protected
32
+
33
+ def last_name_initials
34
+ raise NotImplementedError
35
+ end
36
+
37
+ def contact
38
+ raise NotImplementedError
39
+ end
40
+
41
+ end
@@ -0,0 +1,2 @@
1
+ class UniqueStudentError < ArgumentError
2
+ end
metadata ADDED
@@ -0,0 +1,49 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: student_list_yaml_gem
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - TelariL
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2026-01-04 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description:
14
+ email:
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - lib/data_list.rb
20
+ - lib/data_list_student_short.rb
21
+ - lib/data_table.rb
22
+ - lib/student.rb
23
+ - lib/student_list_yaml.rb
24
+ - lib/student_short.rb
25
+ - lib/super_student.rb
26
+ - lib/unique_student_error.rb
27
+ homepage:
28
+ licenses: []
29
+ metadata: {}
30
+ post_install_message:
31
+ rdoc_options: []
32
+ require_paths:
33
+ - lib
34
+ required_ruby_version: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - ">="
37
+ - !ruby/object:Gem::Version
38
+ version: '0'
39
+ required_rubygems_version: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ requirements: []
45
+ rubygems_version: 3.4.20
46
+ signing_key:
47
+ specification_version: 4
48
+ summary: Students list stored in YAML
49
+ test_files: []