-
Notifications
You must be signed in to change notification settings - Fork 0
/
conflicts.py
178 lines (137 loc) · 5.81 KB
/
conflicts.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
import conditions
# conflict_types = ((1, 'Совпадение аудиторий'),
# (2, 'Совпадение преподавателей'))
class BaseConflict:
title = 'Название конфликта'
type = -1
def __init__(self):
super().__init__()
self.compare_fields = None
def fill_conflict_db(self, conflicts, type, sched_conflict_model, group):
# pk = sched_conflict_model.pk.qualified_col_name
for conflict_pk in conflicts:
new_entry = {
sched_conflict_model.conflict.qualified_col_name: type,
sched_conflict_model.sched_item.qualified_col_name: conflict_pk,
sched_conflict_model.con_group.qualified_col_name: group
}
sched_conflict_model.insert(new_entry)
def full_recalculate(self, data, sched_model, sched_conflicts_model):
pk = sched_model.pk.qualified_col_name
used = set()
cur_group = 1
for entry in data:
conflicting_entries = []
if entry[pk] in used:
continue
conflicting_entries.append(entry[pk])
used.add(entry[pk])
for suspect in data:
if suspect[pk] in used:
continue
if self.compare(entry, suspect, sched_model):
used.add(suspect[pk])
conflicting_entries.append(suspect[pk])
if len(conflicting_entries) > 1:
self.fill_conflict_db(conflicting_entries, self.type, sched_conflicts_model, cur_group)
cur_group += 1
'''return true if conflict exists'''
def compare(self, entry, suspect, sched_model):
if not self.compare_fields:
return False
for field in self.compare_fields:
if entry[field.qualified_col_name] != suspect[field.qualified_col_name]:
return False
return True
class AudienceOverlap(BaseConflict):
title = 'Совпадение аудиторий'
alias = 'audience_overlap'
type = 1
def __init__(self, sched_model):
super().__init__()
self.compare_fields = (
sched_model.weekday,
sched_model.lesson,
sched_model.audience
)
class TeacherFracture(BaseConflict):
title = 'Разрыв преподавателя'
alias = 'teacher_fracture'
type = 2
def __init__(self, sched_model):
super().__init__()
self.compare_fields = (
sched_model.weekday,
sched_model.lesson,
sched_model.teacher
)
class GroupFracture(BaseConflict):
title = 'Разрыв группы'
alias = 'group_fracture'
type = 3
def __init__(self, sched_model):
super().__init__()
self.compare_fields = (
sched_model.weekday,
sched_model.lesson,
sched_model.group
)
class PossibleDuplicates(BaseConflict):
title = 'Возможные дубликаты'
alias = 'possible_duplicates'
type = 4
def __init__(self, sched_model):
super().__init__()
self.compare_fields = (
sched_model.lesson,
sched_model.subject,
sched_model.audience,
sched_model.group,
sched_model.teacher,
sched_model.type,
sched_model.weekday,
)
all_conflicts = None
def initialize(sched_model):
global all_conflicts
all_conflicts = (
AudienceOverlap(sched_model),
TeacherFracture(sched_model),
GroupFracture(sched_model),
PossibleDuplicates(sched_model)
)
def recalculate_all(cur, sched_conflicts_model, conflicts_model, sched_model):
# RECREATE ALL TABLES
cur.execute('''RECREATE TABLE {table_name}
(
ID Integer GENERATED BY DEFAULT AS IDENTITY,
CONFLICT_ID Integer NOT NULL,
SCHED_ID Integer NOT NULL,
CON_GROUP Integer NOT NULL,
PRIMARY KEY (ID)
)'''.format(table_name=sched_conflicts_model.table_name))
cur.execute('''RECREATE TABLE {table_name}
(
ID Integer NOT NULL,
NAME Varchar(255) NOT NULL,
PRIMARY KEY (ID)
);
'''.format(table_name=conflicts_model.table_name))
cur.execute('''ALTER TABLE {sched_conflicts_table_name} ADD
FOREIGN KEY ({conflict_id_col_name}) REFERENCES {conflicts_table_name} (ID)
ON DELETE CASCADE
ON UPDATE CASCADE;'''.format(sched_conflicts_table_name=sched_conflicts_model.table_name,
conflict_id_col_name=sched_conflicts_model.conflict.col_name,
conflicts_table_name=conflicts_model.table_name))
cur.execute('''ALTER TABLE {sched_conflicts_table_name} ADD
FOREIGN KEY ({conflict_id_col_name}) REFERENCES {conflicts_table_name} (ID)
ON DELETE CASCADE
ON UPDATE CASCADE;'''.format(sched_conflicts_table_name=sched_conflicts_model.table_name,
conflict_id_col_name=sched_conflicts_model.sched_item.col_name,
conflicts_table_name=sched_model.table_name))
cur.transaction.commit()
cur.executemany('INSERT INTO {tablename} values (?, ?)'.format(tablename=conflicts_model.table_name),
[(idx+1, c.title) for idx, c in enumerate(all_conflicts)])
data = sched_model.fetch_all(return_fields=sched_model.fields)
for conflict in all_conflicts:
conflict.full_recalculate(data, sched_model, sched_conflicts_model)