student_list 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: c73afb232da5b5b584617cc799aff8d41f4143ccd97cd61fca69bb2617c8d7cb
4
+ data.tar.gz: ff75edc9d6bb9ea223d1b45eccbae397d110792ace37961140a9daa1bba3ffd7
5
+ SHA512:
6
+ metadata.gz: 93ed939b37348e7ff691ad7e589e29aca82a303eed09031556b90e274e807e58aa30123ac062d4cb1bc024415e92f3b988691f9cacd74d259adc4555fd67b4f6
7
+ data.tar.gz: 03b7cc945f1e3c87b8940b5070c360dfd29a42187aff9554cdb0e165883e9cc2428a025f5b50b21c7196a6e0d7b58a624a940c1359bcebad7d031d9644d1fd7e
data/lib/data_list.rb ADDED
@@ -0,0 +1,58 @@
1
+ require_relative "data_table"
2
+
3
+ class DataList
4
+
5
+ def object_list=(new_object_list)
6
+ @object_list = new_object_list
7
+ clear_selected
8
+ end
9
+
10
+ attr_reader :object_list, :selected
11
+
12
+ def initialize(object_list: )
13
+ @object_list = object_list
14
+ @selected = []
15
+ @atribute_names = get_atribute_names unless object_list.empty?
16
+ end
17
+
18
+ def select(number)
19
+ if number >= 0 && number < @object_list.size
20
+ @selected << number unless @selected.include?(number)
21
+ end
22
+ end
23
+
24
+ def get_selected(numbers)
25
+ @selected.map { |index| @object_list[index].id }
26
+ end
27
+
28
+ def get_names()
29
+ ["№"] + @atribute_names
30
+ end
31
+
32
+ def get_data()
33
+ result_data = []
34
+ name_columns = get_atribute_names()
35
+ @object_list.each do |elem|
36
+ hash = Hash.new
37
+ atribute_data = get_atribute_data(elem)
38
+ (0..name_columns.size).each do |index|
39
+ hash[name_columns[index]] = atribute_data[index]
40
+ end
41
+ result_data.append(hash)
42
+ end
43
+ return DataTable.new(result_data)
44
+ end
45
+
46
+ def clear_selected()
47
+ @selected.clear
48
+ end
49
+
50
+ private
51
+ def get_atribute_data(elem)
52
+ raise NotImplementedError, "Метод должен быть реализован в наследнике"
53
+ end
54
+
55
+ def get_atribute_names()
56
+ raise NotImplementedError, "Метод должен быть реализован в наследнике"
57
+ end
58
+ end
@@ -0,0 +1,20 @@
1
+ require_relative "data_list"
2
+ require_relative "student_short"
3
+
4
+ class DataListStudentShort < DataList
5
+ def initialize(student_list)
6
+ super(object_list: student_list)
7
+ end
8
+
9
+ private
10
+
11
+ def get_atribute_names
12
+ ["last_name_initials", "contact", "git"]
13
+ end
14
+
15
+ def get_atribute_data(elem)
16
+ [elem.last_name_initials, elem.contact, elem.git]
17
+ end
18
+ end
19
+
20
+
data/lib/data_table.rb ADDED
@@ -0,0 +1,96 @@
1
+ class DataTable
2
+
3
+
4
+ attr_reader :columns
5
+
6
+ def initialize(objects)
7
+ @table = []
8
+ index = 0
9
+ @columns = []
10
+ return if objects.empty?
11
+ objects.each do |obj|
12
+ if @columns.empty?
13
+ @columns = obj.keys
14
+ @columns.unshift("№")
15
+ end
16
+ if obj.is_a?(Hash)
17
+ record = []
18
+ obj.each do |k, v|
19
+ record.append(v)
20
+ end
21
+ record.unshift(index)
22
+ @table.append(record)
23
+ index += 1
24
+ end
25
+ end
26
+ end
27
+
28
+ def [](row,col)
29
+ @table[row.to_i][1..][[col.to_i]]
30
+ end
31
+
32
+ def count_row
33
+ @table.size
34
+ end
35
+
36
+ def count_column
37
+ return 0 if @table.empty?
38
+ @columns.size
39
+ end
40
+
41
+ def to_s
42
+ return puts "Таблица пуста" if @table.empty?
43
+ column_widths = calculate_column_widths
44
+ print_border(column_widths)
45
+ print_row(@columns, column_widths)
46
+ print_separator(column_widths)
47
+ @table.each do |row|
48
+ print_row(row, column_widths)
49
+ end
50
+ print_border(column_widths)
51
+ end
52
+
53
+ private
54
+
55
+ def calculate_column_widths
56
+ widths = []
57
+ (0...count_column).each do |col|
58
+ max_width = @columns[col].to_s.length
59
+
60
+ @table.each do |row|
61
+ cell_length = row[col].to_s.length
62
+ max_width = cell_length if cell_length > max_width
63
+ end
64
+
65
+ widths << max_width
66
+ end
67
+
68
+ widths
69
+ end
70
+
71
+ def print_border(widths)
72
+ border = "+"
73
+ widths.each do |width|
74
+ border += "#{'-' * (width + 2)}+"
75
+ end
76
+ puts border
77
+ end
78
+
79
+ def print_separator(widths)
80
+ separator = "+"
81
+ widths.each do |width|
82
+ separator += "#{'=' * (width + 2)}+"
83
+ end
84
+ puts separator
85
+ end
86
+
87
+ def print_row(row, widths)
88
+ line = "|"
89
+ row.each_with_index do |cell, index|
90
+ line += " #{cell.to_s.ljust(widths[index])} |"
91
+ end
92
+ puts line
93
+ end
94
+
95
+
96
+ end
data/lib/student.rb ADDED
@@ -0,0 +1,137 @@
1
+ require_relative 'student_template'
2
+
3
+ class Student < TemplateStudent
4
+ include Comparable
5
+
6
+ attr_reader :patronymic, :last_name, :first_name
7
+ def initialize(id: nil,
8
+ first_name: ,
9
+ last_name: ,
10
+ patronymic: nil,
11
+ phone: nil,
12
+ telegram: nil,
13
+ email: nil,
14
+ git: nil)
15
+ self.patronymic = patronymic
16
+ self.last_name = last_name
17
+ self.first_name = first_name
18
+ self.git = git
19
+ self.contact = {telegram: telegram, phone: phone, email: email}
20
+ super(id: id, git: git, contact: contact)
21
+ end
22
+
23
+ def <=>(other)
24
+ return nil unless other.is_a?(Student)
25
+
26
+ self_name = "#{@first_name} #{@last_name} #{@patronymic}".downcase
27
+ other_name = "#{other.first_name} #{other.last_name} #{other.patronymic}".downcase
28
+
29
+ self_name <=> other_name
30
+ end
31
+
32
+ def last_name_initials()
33
+ initials = "#{@first_name[0].upcase}."
34
+ initials += " #{@patronymic[0].upcase}." if @patronymic && !@patronymic.empty?
35
+ return "#{@last_name} #{initials}"
36
+ end
37
+
38
+ def contact()
39
+ if not @telegram.nil?
40
+ return "telegram - #{@telegram}"
41
+ elsif not @email.nil?
42
+ return "email - #{@email}"
43
+ elsif not @phone.nil?
44
+ return "phone - #{@phone}"
45
+ else return nil
46
+ end
47
+ end
48
+
49
+ def contact=(contact)
50
+ contact.each do |contact_type, contact_value|
51
+ case contact_type
52
+ when :telegram
53
+ validator_contact(telegram: contact_value)
54
+ @telegram = contact_value
55
+ when :phone
56
+ validator_contact(phone: contact_value)
57
+ @phone = contact_value
58
+ when :email
59
+ validator_contact(email: contact_value)
60
+ @email = contact_value
61
+ else
62
+ raise ArgumentError, "Указан верный тип контакта, допустимы контакты с типом tg, email, phone. Вы ввели тип #{contact_type}"
63
+ end
64
+ end
65
+ end
66
+
67
+ def to_s
68
+ info = ["ID: #{@id}", "Фамилия: #{@last_name}", "Имя: #{@first_name}"]
69
+ info << "Отчество: #{@patronymic}" if @patronymic
70
+ info << "Телефон: #{@phone}" if @phone
71
+ info << "Телеграм: #{@telegram}" if @telegram
72
+ info << "Почта: #{@email}" if @email
73
+ info << "Гит: #{self.git}" if self.git
74
+ info.join("\n")
75
+
76
+ end
77
+
78
+
79
+ def self.valid_email?(email)
80
+ return (email.nil? or email =~ /\A[\p{L}0-9+\-.]+@[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z/ui)
81
+ end
82
+
83
+ def self.valid_phone?(phone)
84
+ return (phone.nil? or phone =~ /^(\+7|8)?[\s-]?\(?(\d{3})\)?[\s-]?(\d{3})[\s-]?(\d{2})[\s-]?(\d{2})$/)
85
+ end
86
+
87
+ def self.valid_telegram?(telegram)
88
+ return telegram.nil? || telegram.empty? || telegram.match?(/^@[a-zA-Z0-9_]{5,32}$/)
89
+ end
90
+
91
+ def self.valid_git?(git)
92
+ return (git.nil? or git =~ /^https:\/\/(github|gitlab)\.com\/[a-zA-Z0-9_-]+\/?$/)
93
+ end
94
+
95
+ def self.valid_name?(student_names)
96
+ return (not student_names.nil? and student_names =~ /^[A-ZА-Я][a-zа-я]*$/)
97
+ end
98
+
99
+
100
+ private
101
+ def self.attr_writer_with_validation(*attributes)
102
+ attributes.each do |attr|
103
+ define_method("#{attr}=") do |val|
104
+ valid_method = "valid_#{attr}?"
105
+ if [:patronymic, :last_name, :first_name].include?(attr)
106
+ valid_method = "valid_name?"
107
+ if val.nil? and [:patronymic].include?(attr)
108
+ return
109
+ end
110
+ end
111
+ if self.class.respond_to?(valid_method) && self.class.send(valid_method, val)
112
+ instance_variable_set("@#{attr}", val)
113
+ else
114
+ raise ArgumentError, "Невалидное значение #{attr}"
115
+ end
116
+ end
117
+ end
118
+ end
119
+
120
+ def validator_contact(**kwargs)
121
+ kwargs.each do |arg, val|
122
+ next if val.nil?
123
+ case arg
124
+ when :phone
125
+ raise ArgumentError, "Ошибка валидации #{arg}" if not Student.valid_phone?(val)
126
+ when :email
127
+ raise ArgumentError, "Ошибка валидации #{arg}" if not Student.valid_email?(val)
128
+ when :telegram
129
+ raise ArgumentError, "Ошибка валидации #{arg}" if not Student.valid_telegram?(val)
130
+ else
131
+ raise ArgumentError, "Ошибка данный аргумент не предусмотрен как поле класса - #{arg}"
132
+ end
133
+ end
134
+ end
135
+ attr_writer_with_validation :first_name, :last_name, :patronymic, :git
136
+ end
137
+
@@ -0,0 +1,93 @@
1
+ require 'data_list_student_short'
2
+ require 'student'
3
+ require 'student_short'
4
+
5
+
6
+ class StudentList
7
+ def initialize()
8
+ @students_list = []
9
+ end
10
+
11
+ def excecute_data
12
+ raise NoMethodError, "Обязателен к переопределению"
13
+
14
+ end
15
+
16
+ def commit_data
17
+ raise NoMethodError, "Обязателен к переопределению"
18
+
19
+ end
20
+
21
+ def get_sudent_for_id(id)
22
+ @students_list.find{|student| student.id == id}
23
+ end
24
+
25
+ def get_k_n_student_short_list(k, n, exists_data_list=false)
26
+ start_index = (k - 1) * n
27
+ end_index = start_index + n - 1
28
+ students_slice = @students_list[start_index..end_index] || []
29
+ students_slice.map{|student| StudentShort.from_student(student)}
30
+ if exists_data_list
31
+ exists_data_list.object_list = students_slice
32
+ return exists_data_list
33
+ else
34
+ DataListStudentShort.new(students_slice)
35
+ end
36
+ end
37
+
38
+ def sort_by_initials
39
+ @students_list.sort_by! { |student| student.last_name_initials }
40
+ end
41
+
42
+ def add_student(last_name:, first_name:, patronymic: nil, phone: nil, telegram: nil, email: nil, git: nil)
43
+ new_id = generate_new_id
44
+ student = Student.new(
45
+ id: new_id,
46
+ first_name: first_name,
47
+ last_name: last_name,
48
+ patronymic: patronymic,
49
+ phone: phone,
50
+ telegram: telegram,
51
+ email: email,
52
+ git: git
53
+ )
54
+
55
+ @students_list << student
56
+ commit_data # Сохраняем изменения
57
+ student
58
+ end
59
+
60
+ def update_student(id, last_name:, first_name:, patronymic: nil, phone: nil, telegram: nil, email: nil, git: nil)
61
+ student = get_sudent_for_id(id)
62
+ return false unless student
63
+ student.last_name = last_name
64
+ student.first_name = first_name
65
+ student.patronymic = patronymic if patronymic
66
+ student.git = git if git
67
+ contact = {}
68
+ contact[:phone] = phone if phone
69
+ contact[:telegram] = telegram if telegram
70
+ contact[:email] = email if email
71
+ student.contact = contact unless contact.empty?
72
+ commit_data
73
+ true
74
+ end
75
+
76
+
77
+ def delete_student(id)
78
+ deleted = @students_list.reject! { |student| student.id == id }
79
+ commit_data if deleted
80
+ !deleted.nil?
81
+ end
82
+
83
+ def get_student_short_count
84
+ @students_list.count
85
+ end
86
+
87
+ private
88
+ def generate_new_id
89
+ max_id = @students_list.map { |s| s.id.to_i }.max || 0
90
+ (max_id + 1).to_s
91
+ end
92
+
93
+ end
@@ -0,0 +1,66 @@
1
+ require_relative "student_list"
2
+
3
+
4
+ class StudentListFile < StudentList
5
+ def file_path=(val)
6
+ if File.exist?(val)
7
+ @file_path = val
8
+ return
9
+ end
10
+ raise ArgumentError, "Такого файла не существует"
11
+ end
12
+
13
+ attr_reader :file_path, :students_list
14
+
15
+ def initialize(file_path: )
16
+ self.file_path = file_path
17
+ super()
18
+ file_read
19
+ end
20
+
21
+ def load_file()
22
+ raise NoMethodError, "Обязателен к переопределению"
23
+ end
24
+
25
+ def get_data_write(data)
26
+ raise NoMethodError, "Обязателен к переопределению"
27
+ end
28
+
29
+ def file_read()
30
+ data = load_file
31
+ data.each do |student_data|
32
+ begin
33
+ self.students_list << Student.new(**student_data)
34
+ rescue StandardError => e
35
+ puts "Ошибка создания студента #{student_data}: #{e.message}"
36
+ end
37
+ end
38
+ end
39
+
40
+ def file_write()
41
+ data = self.students_list.map { |student| student_to_hash(student) }
42
+ File.write(@file_path, get_data_write(data))
43
+ end
44
+
45
+ def commit_data
46
+ file_write
47
+ end
48
+
49
+ def read_data
50
+ file_read
51
+ end
52
+
53
+ def student_to_hash(student)
54
+ {
55
+ id: student.id,
56
+ first_name: student.first_name,
57
+ last_name: student.last_name,
58
+ patronymic: student.patronymic,
59
+ phone: student.instance_variable_get(:@phone),
60
+ telegram: student.instance_variable_get(:@telegram),
61
+ email: student.instance_variable_get(:@email),
62
+ git: student.git
63
+ }.compact
64
+ end
65
+
66
+ end
@@ -0,0 +1,83 @@
1
+ require 'json'
2
+ require_relative 'student_list_file'
3
+
4
+ class StudentListJSON < StudentListFile
5
+ def initialize(file_path: )
6
+ super(file_path: file_path)
7
+ end
8
+
9
+ def load_file()
10
+ JSON.parse(File.read(@file_path), symbolize_names: true)
11
+ end
12
+
13
+ def get_data_write(data)
14
+ JSON.pretty_generate(data)
15
+ end
16
+ end
17
+
18
+ # Основная программа
19
+ if __FILE__ == $0
20
+ filename = '/home/danil/design-patterns-template/src/lab_4/students.json'
21
+
22
+ # Создаем экземпляр класса
23
+ student_list = StudentListJSON.new(file_path: filename)
24
+
25
+ puts "Загружено студентов: #{student_list.get_student_short_count}"
26
+
27
+ # Выводим исходный порядок
28
+ puts "\nИсходный список студентов:"
29
+ student_list.students_list.each do |student|
30
+ puts "#{student.last_name_initials} (ID: #{student.id})"
31
+ end
32
+
33
+ # Сортируем по инициалам
34
+ puts "\nПосле сортировки по инициалам:"
35
+ student_list.sort_by_initials
36
+ student_list.students_list.each do |student|
37
+ puts student.last_name_initials
38
+ end
39
+
40
+ # Получаем список (первые 2 элемента)
41
+ puts "\nПолучаем первые 2 студента:"
42
+ short_list = student_list.get_k_n_student_short_list(1, 2)
43
+ puts short_list.get_data()
44
+ # Добавляем нового студента
45
+ puts "\nДобавляем нового студента:"
46
+ new_student = student_list.add_student(
47
+ last_name: "Павлов",
48
+ first_name: "Артем",
49
+ patronymic: "Викторович",
50
+ phone: "+79165554433",
51
+ )
52
+ puts "Добавлен: #{new_student.last_name_initials}"
53
+
54
+ # Получаем студента по ID
55
+ puts "\nПоиск студента по ID 2:"
56
+ found_student = student_list.get_sudent_for_id("2")
57
+ if found_student
58
+ puts "Найден: #{found_student.last_name_initials}"
59
+ end
60
+
61
+ # Обновляем студента
62
+ puts "\nОбновляем студента с ID 3:"
63
+ if student_list.update_student("3",
64
+ last_name: "Волкова",
65
+ first_name: "Мария",
66
+ patronymic: "Александровна",
67
+ )
68
+ puts "Студент обновлен"
69
+ end
70
+
71
+ # Выводим финальный список
72
+ puts "\nФинальный список студентов (#{student_list.get_student_short_count} чел.):"
73
+ student_list.students_list.each do |student|
74
+ puts "#{student.last_name_initials} (ID: #{student.id})"
75
+ end
76
+
77
+ # Демонстрация пагинации
78
+ puts "\nДемонстрация пагинации (по 2 студента на странице):"
79
+ (1..3).each do |page|
80
+ short_list = student_list.get_k_n_student_short_list(page, 2, short_list)
81
+ puts "Страница #{page}: #{short_list.get_data}"
82
+ end
83
+ end
@@ -0,0 +1,83 @@
1
+ require_relative 'student_list_file'
2
+ require 'yaml'
3
+
4
+ class StudentListYAML < StudentListFile
5
+ def initialize(file_path: )
6
+ super(file_path: file_path)
7
+ end
8
+
9
+ def load_file()
10
+ YAML.load_file(@file_path, symbolize_names: true)
11
+ end
12
+
13
+ def get_data_write(data)
14
+ data.to_yaml
15
+ end
16
+ end
17
+
18
+ # Основная программа
19
+ if __FILE__ == $0
20
+ filename = '/home/danil/design-patterns-template/src/lab_4/students.yaml'
21
+
22
+ # Создаем экземпляр класса
23
+ student_list = StudentListYAML.new(file_path: filename)
24
+
25
+ puts "Загружено студентов: #{student_list.get_student_short_count}"
26
+
27
+ # Выводим исходный порядок
28
+ puts "\nИсходный список студентов:"
29
+ student_list.students_list.each do |student|
30
+ puts "#{student.last_name_initials} (ID: #{student.id})"
31
+ end
32
+
33
+ # Сортируем по инициалам
34
+ puts "\nПосле сортировки по инициалам:"
35
+ student_list.sort_by_initials
36
+ student_list.students_list.each do |student|
37
+ puts student.last_name_initials
38
+ end
39
+
40
+ # Получаем список (первые 2 элемента)
41
+ puts "\nПолучаем первые 2 студента:"
42
+ short_list = student_list.get_k_n_student_short_list(1, 2)
43
+ puts short_list.get_data()
44
+ # Добавляем нового студента
45
+ puts "\nДобавляем нового студента:"
46
+ new_student = student_list.add_student(
47
+ last_name: "Павлов",
48
+ first_name: "Артем",
49
+ patronymic: "Викторович",
50
+ phone: "+79165554433",
51
+ )
52
+ puts "Добавлен: #{new_student.last_name_initials}"
53
+
54
+ # Получаем студента по ID
55
+ puts "\nПоиск студента по ID 2:"
56
+ found_student = student_list.get_sudent_for_id("2")
57
+ if found_student
58
+ puts "Найден: #{found_student.last_name_initials}"
59
+ end
60
+
61
+ # Обновляем студента
62
+ puts "\nОбновляем студента с ID 3:"
63
+ if student_list.update_student("3",
64
+ last_name: "Волкова",
65
+ first_name: "Мария",
66
+ patronymic: "Александровна",
67
+ )
68
+ puts "Студент обновлен"
69
+ end
70
+
71
+ # Выводим финальный список
72
+ puts "\nФинальный список студентов (#{student_list.get_student_short_count} чел.):"
73
+ student_list.students_list.each do |student|
74
+ puts "#{student.last_name_initials} (ID: #{student.id})"
75
+ end
76
+
77
+ # Демонстрация пагинации
78
+ puts "\nДемонстрация пагинации (по 2 студента на странице):"
79
+ (1..3).each do |page|
80
+ short_list = student_list.get_k_n_student_short_list(page, 2, short_list)
81
+ puts "Страница #{page}: #{short_list.get_data}"
82
+ end
83
+ end
@@ -0,0 +1,30 @@
1
+ require_relative 'student'
2
+ require_relative 'student_template'
3
+
4
+ class StudentShort < TemplateStudent
5
+ def initialize(id:, last_name_initials:, contact: nil, git: nil)
6
+ @last_name_initials = last_name_initials
7
+ @contact = contact
8
+ super(id: id, contact: contact, git: git)
9
+ end
10
+
11
+ def contact()
12
+ @contact
13
+ end
14
+
15
+ def last_name_initials()
16
+ @last_name_initials
17
+ end
18
+
19
+ def self.from_student(student)
20
+ new(
21
+ id: student.id,
22
+ last_name_initials: student.last_name_initials(),
23
+ contact: student.contact,
24
+ git: student.git)
25
+ end
26
+
27
+ def to_s
28
+ self.short_info
29
+ end
30
+ end
@@ -0,0 +1,34 @@
1
+ class TemplateStudent
2
+
3
+ def contact()
4
+ raise NoMethodError, "Обязателен к переопределению"
5
+ end
6
+
7
+ def last_name_initials()
8
+ raise NoMethodError, "Обязателен к переопределению"
9
+ end
10
+
11
+ attr_reader :id, :git
12
+
13
+ def initialize(id: , contact: nil, git: nil)
14
+ @id = id
15
+ @contact = contact
16
+ @git = git
17
+ end
18
+
19
+ def short_info()
20
+ info = ["ID: #{@id}", "ФИО: #{last_name_initials()}"]
21
+ info << (@contact || "нет контакта")
22
+ info << "Гит: #{@git || 'нет'}"
23
+ info.join(", ")
24
+ end
25
+
26
+ def has_git?
27
+ !git.nil? && !git.empty?
28
+ end
29
+
30
+ def has_contact?
31
+ !contact.nil? && !contact.empty?
32
+ end
33
+
34
+ end
@@ -0,0 +1,14 @@
1
+ # Главный файл gem - загружает все зависимости
2
+ require_relative 'data_list'
3
+ require_relative 'data_table'
4
+ require_relative 'data_list_student_short'
5
+ require_relative 'student'
6
+ require_relative 'student_short'
7
+ require_relative 'students_list'
8
+ require_relative 'student_template'
9
+ require_relative 'student_list'
10
+ require_relative 'student_list_file'
11
+ require_relative 'student_list_json'
12
+ require_relative 'student_list_yaml'
13
+
14
+ puts "✅ StudentList gem loaded successfully!"
metadata ADDED
@@ -0,0 +1,68 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: student_list
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - KotDev
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2025-10-31 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: psych
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3.0'
27
+ description: Manage student lists with YAML and JSON storage
28
+ email:
29
+ - kotikov.lil@bk.ru
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - lib/data_list.rb
35
+ - lib/data_list_student_short.rb
36
+ - lib/data_table.rb
37
+ - lib/student.rb
38
+ - lib/student_list.rb
39
+ - lib/student_list_file.rb
40
+ - lib/student_list_json.rb
41
+ - lib/student_list_yaml.rb
42
+ - lib/student_short.rb
43
+ - lib/student_template.rb
44
+ - lib/students_list.rb
45
+ homepage:
46
+ licenses:
47
+ - MIT
48
+ metadata: {}
49
+ post_install_message:
50
+ rdoc_options: []
51
+ require_paths:
52
+ - lib
53
+ required_ruby_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: '0'
58
+ required_rubygems_version: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ requirements: []
64
+ rubygems_version: 3.5.11
65
+ signing_key:
66
+ specification_version: 4
67
+ summary: Student list management
68
+ test_files: []