rafmycat 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: b0ab5d843d7fa6566e1e622e7229c57d55adf9c1448078fca5efc6ca478662d4
4
+ data.tar.gz: 74c17f5d2462bd4813451caad7a764827fb8671d2f4fac210f8f03ea4751d3df
5
+ SHA512:
6
+ metadata.gz: 10efbdefa9191db148fa470cd94298fed578931e756f2566f7d18dfe93349a07e1d95648fe4826c0174fdbadcb5a7220367f5a19622837fda3783b113f115a75
7
+ data.tar.gz: e97e40fec873db781f66a57e8f81093add9535849fb6d3b1fda636725c6928cdd29238fc858eab3e2cacaab47460a4862286fd2b57fc5917123e1a7db09a6f5b
data/Documentation.md ADDED
@@ -0,0 +1,33 @@
1
+ The TabStudentsController class is a controller for working with the interface for interacting with objects of the Student type.
2
+
3
+ Methods of the class:
4
+
5
+ 1. initialize(view) - constructor of the class, takes a view object and creates an empty object of the type
6
+ DataListStudentShort, which is assigned the add_listener method with the view argument, as a result of which the view
7
+ is set as a listener for data state change events (data_list).
8
+ 2. on_view_created is a method that initializes an object of the StudentRepository type, which is used for interaction
9
+ with the database, and if an error occurs connecting to the database displays a dialog box with an error message.
10
+ 3. show_view is a method that displays the main application window.
11
+ 4. show_modal_add is a method that displays a modal window for creating a new student record.
12
+ Creates an instance of the StudentInputFormControllerCreate controller and passes it a reference to the current controller,
13
+ creates an object of the StudentInputForm type and passes it a reference to the controller. Then it displays the modal window.
14
+ 5. show_modal_edit(current_page, per_page, selected_row) is a method that displays the modal window for
15
+ editing a student record. Takes the values of the current page (current_page), the number of records on the page
16
+ (per_page) and the selected row (selected_row). Calculates the number of the selected student and selects his id from
17
+ the DataListStudentShort object, then passes it to the StudentInputFormControllerEdit controller, creates an object of the type
18
+ StudentInputForm and passes it a link to the controller. After that, it displays a modal window.
19
+ 6. delete_selected(current_page, per_page, selected_row) is a method that deletes the selected student record.
20
+ Takes the values of the current page (current_page), the number of records on the page (per_page)
21
+ and the selected row (selected_row). Calculates the number of the selected student and selects his id from the DataListStudentShort object,
22
+ then deletes the record using the remove_student method from the StudentRepository object.
23
+ 7. refresh_data(page, per_page) is a method that updates the data in the list of students. Takes the values
24
+ of the current page (page) and the number of entries on the page (per_page).
25
+ Calls a method of the StudentRepository paginated_short_students type to get data in the DataListStudentShort object format.
26
+ Updates information about the number of students using the update_student_count method of the view.
27
+
28
+ The Student_Input_Form_Controller_Edit controller and Student_Input_Form_Controller_Create are forms
29
+ for modifying and creating students into the database, respectively.
30
+
31
+ The student, student_base and student_short models are a student model with various fields and methods
32
+ for setting, receiving and processing information. Student_base - super class,
33
+ and student_short is the short information about the student.
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 NullExp
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Raf
4
+ VERSION = "1.0.0"
5
+ end
data/lib/raf.rb ADDED
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "raf/version"
4
+
5
+ module Raf
6
+ Dir[File.dirname(__FILE__) + '/source/**/*.rb'].each { |file|
7
+ puts file
8
+ require file
9
+ }
10
+ end
@@ -0,0 +1,37 @@
1
+ class DBUniversity
2
+ # @@ - кринж, так как если данный класс будет наследовать, то переменная класса переопределится с таким же значением
3
+ private_class_method :new
4
+ # Создаем мьютекс для синхронизации доступа к переменной @instance он позволяет "захватить" доступ к общему ресурсу,
5
+ # чтобы другие потоки не могли получить доступ к защищенному коду, пока мьютекс не будет освобожден.
6
+ @instance_mutex = Mutex.new
7
+
8
+ # Инициализируем объект, открывая БД и настраивая её на возвращение результатов в виде хешей
9
+ def initialize
10
+ @client = SQLite3::Database.open 'C:\Users\valen\RubymineProjects\untitled\identifier.sqlite'
11
+ @client.results_as_hash = true
12
+ end
13
+
14
+
15
+ # Метод, возвращает ЕДИНСТВЕННЫЙ экземпляр класса DBUniversity.
16
+ def self.instance
17
+ return @instance if @instance
18
+
19
+ # Иначе захватываем мьютекс, чтобы ТОЛЬКО ОДИН поток мог создать экземпляр класса.
20
+ @instance_mutex.synchronize do
21
+ @instance ||= new
22
+ end
23
+ @instance
24
+ end
25
+
26
+ # Методы, принимают SQL-запрос (и параметры), возвращает результаты запроса.
27
+ def prepare_exec(statement, *params)
28
+ @client.prepare(statement).execute(*params)
29
+ end
30
+
31
+ def query(statement)
32
+ @client.query(statement)
33
+ end
34
+
35
+
36
+ end
37
+
@@ -0,0 +1,70 @@
1
+ require_relative 'DBUniversity'
2
+ require 'json'
3
+ require 'sqlite3'
4
+ class StudentListDBAdapter
5
+
6
+ def initialize
7
+ self.client = DBUniversity.instance
8
+ end
9
+
10
+ #last_name, first_name, paternal_name, phone, telegram, email, git
11
+ def into_hash(arr)
12
+ attrs = {}
13
+ i=0
14
+ %i[id last_name first_name paternal_name phone telegram email git].each do |attr|
15
+ attrs[attr] = arr[i] unless arr[i].nil?
16
+ i=i+1
17
+ end
18
+ attrs
19
+ end
20
+ def student_by_id(id_student)
21
+ hash = client.prepare_exec('SELECT * FROM students WHERE id = ?', id_student).first
22
+ hash=into_hash(hash)
23
+ return nil if hash.nil?
24
+
25
+ Student.new(**hash)
26
+ end
27
+
28
+ def get_k_n_student_short_list(k,n,data_list=nil )
29
+ offset = (k - 1) * n
30
+ students = client.prepare_exec('SELECT * FROM students LIMIT ?, ?', offset, n)
31
+ slice = students.map { |h|
32
+ h = h.transform_keys(&:to_sym)
33
+ StudentShort.new(Student.into_hash(h))
34
+ }
35
+ return DataListStudentShort.new(slice) if data_list.nil?
36
+
37
+ data_list.replace_objects(slice)
38
+ data_list
39
+ end
40
+
41
+ def add_student(student)
42
+ st = client.prepare_exec('insert into students (last_name, first_name, paternal_name, phone,
43
+ telegram, email, git) VALUES (?, ?, ?, ?, ?, ?, ?)',*student_attr(student))
44
+ end
45
+
46
+ def replace_student(id_student, student)
47
+ st ='UPDATE students SET last_name=?, first_name=?, paternal_name=?, phone=?, telegram=?, email=?, git=? WHERE id=?'
48
+ client.prepare_exec(st,*student_attr(student), id_student)
49
+ end
50
+
51
+ def delete_student(id_student)
52
+ client.prepare_exec('DELETE FROM students WHERE id = ?', id_student)
53
+ end
54
+
55
+ def count_student
56
+ client.query('SELECT COUNT(id) FROM students').next[0]
57
+ end
58
+
59
+ private
60
+
61
+ attr_accessor :client
62
+
63
+ def student_attr(student)
64
+ [student.last_name, student.first_name, student.paternal_name,
65
+ student.phone, student.telegram,
66
+ student.email, student.git]
67
+ end
68
+
69
+ end
70
+
@@ -0,0 +1,119 @@
1
+ require_relative 'window'
2
+ require_relative 'logicFromWindow'
3
+ require_relative 'studentList'
4
+ require_relative 'Students_list_DB'
5
+ require_relative '../data/data_list_student_short'
6
+ require_relative 'studentFileAdapter'
7
+ require_relative 'StudentList'
8
+ require_relative '../strategy/students_list_json'
9
+ require_relative 'student_create_form_controller'
10
+ require_relative 'student_edit_form_controller'
11
+ require_relative 'student_git_form_controller'
12
+ require_relative 'student_contact_form_controller'
13
+ require_relative 'logger_holder'
14
+
15
+ #require 'win32api'
16
+ require 'glimmer-dsl-libui'
17
+
18
+
19
+ class StudentListController
20
+ attr_reader :view
21
+ def initialize(view)
22
+ LoggerHolder.instance.debug('StudentListController: init start')
23
+ @view = view
24
+ @data_list = DataListStudentShort.new([])
25
+ @data_list.add_observer(@view)
26
+ LoggerHolder.instance.debug('StudentListController: init done')
27
+ end
28
+
29
+ # Метод инициализирует экземпляр класса StudentList с помощью StudentListDBAdapter.
30
+ def on_view_created
31
+ #@student_list = StudentList.new(StudentFileAdapter.new(StudentListJson.new, './Lab_2/students.json'))
32
+ begin
33
+ @student_list=StudentList.new(StudentListDBAdapter.new)
34
+ LoggerHolder.instance.debug('StudentListController: view create')
35
+ rescue
36
+ on_db_conn_error
37
+ end
38
+
39
+ end
40
+
41
+ # Отображает представление view.
42
+ def show_view
43
+ @view.create.show
44
+ end
45
+ def show_add_student()
46
+ LoggerHolder.instance.debug('StudentListController: show add student')
47
+ controller = StudentCreateFormController.new(self)
48
+ view = StudentCreateForm.new(controller)
49
+ controller.view=view
50
+ view.create.show
51
+ end
52
+
53
+ def show_edit_student(current_page, per_page, selected_row)
54
+ LoggerHolder.instance.debug('StudentListController: show edit name')
55
+ student_num = selected_row
56
+ @data_list.select_elem(student_num)
57
+ student_id = @data_list.selected_id
58
+ controller = StudentEditFormController.new(self, student_id)
59
+ view = StudentCreateForm.new(controller)
60
+ controller.view=view
61
+ view.create.show
62
+ end
63
+ def show_git_student(current_page, per_page, selected_row)
64
+ LoggerHolder.instance.debug('StudentListController: show edit git')
65
+ student_num = selected_row
66
+ @data_list.select_elem(student_num)
67
+ student_id = @data_list.selected_id
68
+ controller = StudentGitFormController.new(self, student_id)
69
+ view = StudentCreateForm.new(controller)
70
+ controller.view=view
71
+ view.create.show
72
+ end
73
+
74
+ def show_contact_student(current_page, per_page, selected_row)
75
+ LoggerHolder.instance.debug('StudentListController: show edit git')
76
+ student_num = selected_row
77
+ @data_list.select_elem(student_num)
78
+ student_id = @data_list.selected_id
79
+ controller = StudentContactFormController.new(self, student_id)
80
+ view = StudentCreateForm.new(controller)
81
+ controller.view=view
82
+ view.create.show
83
+ end
84
+ def delete_selected(current_page, per_page, selected_row)
85
+ #begin
86
+ #student_num = (current_page - 1) * per_page + selected_row
87
+ student_num = selected_row
88
+ puts student_num
89
+ @data_list.select_elem(student_num)
90
+ student_id = @data_list.selected_id
91
+ @student_list.delete_student(student_id)
92
+ #rescue
93
+ #on_db_conn_error
94
+ #end
95
+ end
96
+
97
+ # Oбновляет данные списка студентов.
98
+ # Получает короткий список из БД с помощью get_k_n_student_short_list.
99
+ # Обновляет экземпляр @data_list новым списком.
100
+ # Обновляет счетчик студентов на представлении @view с помощью метода update_student_count.
101
+ def refresh_data(k, n)
102
+ #Сформировать список исключительных ситуаций, который может возникнуть при выполнении включения программ
103
+ #begin
104
+ #raise StandardError, "Error DB"
105
+ @data_list = @student_list.get_k_n_student_short_list(k, n, @data_list)
106
+ @view.update_student_count(@student_list.count_student)
107
+ # rescue
108
+ # on_db_conn_error
109
+ # end
110
+ end
111
+
112
+ def on_db_conn_error
113
+ api = Win32API.new('user32', 'MessageBox', ['L', 'P', 'P', 'L'], 'I')
114
+ api.call(0, "No connection to DB", "Error", 0)
115
+ exit(false)
116
+ end
117
+
118
+
119
+ end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+ require_relative 'data_table'
3
+ class DataList
4
+ #private_class_method :new
5
+ attr_writer :list
6
+ def initialize(objects)
7
+ #self.sel_objects = []
8
+ self.list = objects #self.objects_list
9
+ @observers = []
10
+ end
11
+
12
+ def add_observer(observer)
13
+ @observers.append(observer)
14
+ end
15
+
16
+ def remove_observer(observer)
17
+ @observers.delete(observer)
18
+ end
19
+ def notify
20
+ @observers.each { |observer| observer.on_datalist_changed(get_data) }
21
+ end
22
+ # def select(number)
23
+ # #raise ArgumentError, "arg 'number' not Integer" if number.class != Integer
24
+ # sel_objects.append(number)
25
+ # end
26
+
27
+ def select_elem(number)
28
+ self.sel_object = number
29
+ end
30
+
31
+ # очистить массив выборки
32
+ # def clear_select
33
+ # self.sel_objects = []
34
+ # end
35
+
36
+ # def get_selected
37
+ # return [] if sel_objects.empty?
38
+ # list_id=[]
39
+ # sel_objects.each do |i|
40
+ # list_id.append(list[i].id)
41
+ # end
42
+ # list_id
43
+ # end
44
+ def selected_id
45
+ list[sel_object].id
46
+ end
47
+
48
+ def get_data
49
+ index_id=0
50
+ dt = list.inject([]) do |res, object|
51
+ row=[index_id]
52
+ row.append(*table_fields(object))
53
+ index_id+=1
54
+ res<<row
55
+ end
56
+ DataTable.new(dt)
57
+ end
58
+
59
+ def replace_objects(objects)
60
+ self.list = objects.dup
61
+ notify
62
+ end
63
+
64
+ protected
65
+ def get_names
66
+
67
+ end
68
+
69
+ def table_fields(object)
70
+ []
71
+ end
72
+
73
+ private
74
+ attr_accessor :sel_object
75
+ attr_reader :list
76
+ end
@@ -0,0 +1,15 @@
1
+ require_relative 'data_list'
2
+ class DataListStudentShort<DataList
3
+
4
+ def initialize(objects)
5
+ super(objects)
6
+ end
7
+
8
+ def get_names
9
+ ["№","ФИО", "Гит", "Контаке"]
10
+ end
11
+ #Переопределенный метод
12
+ protected def table_fields(object)
13
+ [object.shortName, object.git, object.contact]
14
+ end
15
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ class DataTable
4
+
5
+ attr_reader :str_count, :st_count
6
+
7
+ def initialize(table)
8
+ self.str_count = table.length
9
+
10
+ max_c=0
11
+ table.each do |el|
12
+ max_c = el.length if el.size > max_c
13
+ end
14
+ self.st_count = max_c
15
+ self.table = table
16
+ end
17
+
18
+
19
+ def get_elem(str, st)
20
+ return nil if str>=str_count
21
+ return nil if st>=st_count
22
+ table[str][st]
23
+ end
24
+
25
+ def to_my_array
26
+ table.dup
27
+ end
28
+
29
+ def to_s
30
+ table.map { |row| "[#{row.join(', ')}]" }.join("\n")
31
+ end
32
+
33
+
34
+ private
35
+ attr_accessor :table
36
+ attr_writer :str_count, :st_count
37
+
38
+ end
@@ -0,0 +1,20 @@
1
+ class LoggerHolder
2
+ private_class_method :new
3
+ @instance_mutex = Mutex.new
4
+
5
+ attr_reader :logger
6
+
7
+ def initialize
8
+ @logger = Logger.new(STDOUT)
9
+ end
10
+
11
+ def self.instance
12
+ return @instance.logger if @instance
13
+
14
+ @instance_mutex.synchronize do
15
+ @instance ||= new
16
+ end
17
+
18
+ @instance.logger
19
+ end
20
+ end
@@ -0,0 +1,182 @@
1
+ require_relative 'controller'
2
+ require_relative 'window'
3
+ require_relative '../data/data_table'
4
+ require_relative 'student_create_form'
5
+ class LogicFromWindow
6
+ include Glimmer
7
+ STUDENTS_PER_PAGE = 10
8
+ def initialize
9
+ @controller = StudentListController.new(self)
10
+ @current_page = 1
11
+ @total_count = 0
12
+ end
13
+ def on_create
14
+ @controller.on_view_created
15
+ @controller.refresh_data(@current_page, STUDENTS_PER_PAGE)
16
+ end
17
+
18
+ # Метод наблюдателя datalist
19
+ def on_datalist_changed(new_table)
20
+ arr = new_table.to_my_array
21
+ arr.map do |row|
22
+ row[3] = row[3][:value] unless row[3].nil?
23
+ #row[3] = row[3][:phone] || row[3][:email] || row[3][:telegram] unless row[3].nil?
24
+ end
25
+ @table.model_array = arr
26
+ end
27
+ def update_student_count(new_cnt)
28
+ @total_count = new_cnt
29
+ @page_label.text = "#{@current_page} / #{(@total_count / STUDENTS_PER_PAGE.to_f).ceil}"
30
+ end
31
+ def delete
32
+ @controller.delete_selected(@current_page, STUDENTS_PER_PAGE, @table.selection) unless @table.selection.nil?
33
+ @controller.refresh_data(@current_page, STUDENTS_PER_PAGE)
34
+ end
35
+ def create
36
+ root_container = horizontal_box {
37
+
38
+ # 1 область
39
+ vertical_box {
40
+ form {
41
+ stretchy false
42
+
43
+ @filter_last_name_initials = entry {
44
+ stretchy false
45
+ label 'Фамилия И. О.'
46
+ }
47
+ @filters = {}
48
+ fields = [[:git, 'Гит'], [:email, 'Почта'], [:phone, 'Телефон'], [:telegram, 'Телеграм']]
49
+ fields.each do |field|
50
+ @filters[field[0]] = {}
51
+ @filters[field[0]][:combobox] = combobox {
52
+ stretchy false
53
+ label "#{field[1]} имеется?"
54
+ items ['Не важно', 'Да', 'Нет']
55
+ selected 0
56
+
57
+ on_selected do
58
+ if @filters[field[0]][:combobox].selected == 1
59
+ @filters[field[0]][:entry].read_only = false
60
+ else
61
+ @filters[field[0]][:entry].text = ''
62
+ @filters[field[0]][:entry].read_only = true
63
+ end
64
+ end
65
+ }
66
+ @filters[field[0]][:entry] = entry {
67
+ stretchy false
68
+ label field[1]
69
+ read_only true
70
+ }
71
+ end
72
+ }
73
+ }
74
+ #2 область
75
+ vertical_box {
76
+ stretchy true
77
+ @table = refined_table(
78
+ table_editable: false,
79
+ filter: lambda do |row_hash, query|
80
+ utf8_query = query.force_encoding("utf-8")
81
+ row_hash['Фамилия И. О'].include?(utf8_query)
82
+ end,
83
+ table_columns: {
84
+ '#' => :text,
85
+ 'Фамилия И. О' => :text,
86
+ 'Гит' => :text,
87
+ 'Контакт' => :text
88
+ },
89
+ )
90
+
91
+ @pages = horizontal_box {
92
+ stretchy false
93
+
94
+ button("<") {
95
+ stretchy true
96
+
97
+ on_clicked do
98
+ @current_page = [@current_page - 1, 1].max
99
+ @controller.refresh_data(@current_page, STUDENTS_PER_PAGE)
100
+ end
101
+
102
+ }
103
+ @page_label = label("...") { stretchy false }
104
+ button(">") {
105
+ stretchy true
106
+
107
+ on_clicked do
108
+ @current_page = [@current_page + 1, (@total_count / STUDENTS_PER_PAGE.to_f).ceil].min
109
+ @controller.refresh_data(@current_page, STUDENTS_PER_PAGE)
110
+ end
111
+ }
112
+ }
113
+ }
114
+ # 3 область
115
+ vertical_box{
116
+ stretchy true
117
+ button('Добавить') {
118
+ stretchy false
119
+ on_clicked {
120
+ @controller.show_add_student
121
+ }
122
+ }
123
+
124
+ button('Изменить ФИО') {
125
+ stretchy false
126
+ on_clicked {
127
+ puts "до вызова контроллера"
128
+ @controller.show_edit_student(@current_page, STUDENTS_PER_PAGE, @table.selection) unless @table.selection.nil?
129
+ @controller.refresh_data(@current_page, STUDENTS_PER_PAGE)
130
+ } }
131
+
132
+ button('Изменить git') { stretchy false
133
+ on_clicked{
134
+ @controller.show_git_student(@current_page, STUDENTS_PER_PAGE, @table.selection) unless @table.selection.nil?
135
+ @controller.refresh_data(@current_page, STUDENTS_PER_PAGE)
136
+ }
137
+ }
138
+ button('Изменить контакт') { stretchy false
139
+ on_clicked{
140
+ @controller.show_contact_student(@current_page, STUDENTS_PER_PAGE, @table.selection) unless @table.selection.nil?
141
+ @controller.refresh_data(@current_page, STUDENTS_PER_PAGE)
142
+ }
143
+ }
144
+
145
+ button('Удалить') {
146
+ stretchy false
147
+
148
+ on_clicked {
149
+ delete
150
+ }
151
+ }
152
+ button('Обновить') {
153
+ stretchy false
154
+ on_clicked {
155
+ @controller.refresh_data(@current_page, STUDENTS_PER_PAGE)
156
+ }
157
+ }
158
+ }
159
+ }
160
+ on_create
161
+ root_container
162
+ end
163
+
164
+ def refresh_current_page
165
+ @controller.refresh_data(@current_page, STUDENTS_PER_PAGE)
166
+ end
167
+
168
+ private
169
+
170
+ def sort_by_column(column_index)
171
+ data = @table.cell_rows
172
+ if @sort_column == column_index
173
+ data.reverse!
174
+ @sort_order = (@sort_order == :asc) ? :desc : :asc
175
+ else
176
+ @sort_column = column_index
177
+ @sort_order = :asc
178
+ data.sort_by! { |row| row[column_index].to_s }
179
+ end
180
+ @table.cell_rows = data
181
+ end
182
+ end