-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathscheduleer.py
593 lines (548 loc) · 26 KB
/
scheduleer.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
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
'''
END OF SUMMER NOTES:
-Big Problem: currently, it produces just 20 schedules for 20 different orders, and they are often fairly similar. This will make too few schedules for round 2 bidding, possibly leaving someone with only schedules they didn't really want. Some ways to fix this:
- Make more schedules, about 2 more for each user, where that user picks their entire schedule first before doing a lottery with everyone else.
- Make more schedules, where half of the people randomly pick twice in a row. Or maybe just completely random order and not lottery-style back and forth.
- During lottery rounds, when picking the maximum-new-value section, pick randomly from the list of ties for max-nv, instead of just picking the first one.
- Do more rounds of trading, where you occasionally randomly allow for some zero-value trades.
-Assigning bids is trickier than I thought for users. I ended up with a 7:00 PM class because the sect_bid wasn't negative enough for to overcome my preps_bid. Users should be advised that:
- They will definitely get some sections they bid high on. Note that that gives all sections of those courses automatic bonuses according to their preps_bid.
- After they have their 2 favorites, simulate some third options, assuming their favorites are gone. Does the total bids line up in the order that they want them?
-TODO:
- Finish testing correctness of want_tables
- Make database models for round 1 results
- Make database models for round 2 bids and round 2 results
- Write back-end code for round 2 bidding and testing
- The whole dang front end
'''
from app import app, db
from app.models import User, Post, Section, SectionBid, UserBids
import csv
import datetime
import test_user_data
from copy import deepcopy
from orderer import orderer
import cycler
from config import semester, non_participants, knocking_adj_penalty
@app.shell_context_processor
def make_shell_context():
return {'db': db, 'User': User, 'Post': Post,
'Section': Section, 'SectionBid': SectionBid,
'UserBids': UserBids}
class Sect:
def __init__(self, choice, course, start, end,
MW, TTh, MTWTh, taken_by, units, room):
self.choice = choice # eg, 1 or 127
self.index = 0 # index in nv, user_bids.sect_bids MUST BE SET
self.course = course # eg 110 or 275
self.start = start # datetime.time object
self.end = end # datetime.time object
self.MW = MW # boolean
self.TTh = TTh # boolean
self.MTWTh = MTWTh # boolean
self.taken_by = taken_by # string: 'Tchertchian E' or 'Hoglund W'
self.units = units # int
self.room = room # string, eg '1003B'
def __repr__(self):
return('choice: {} index: {} course: {} taken_by: {}'
.format(self.choice, self.index, self.course, self.taken_by))
class UBids:
def __init__(self, user, semester, timestamp):
self.user = user # User.id from db
self.index = 0 # index in ub, nv MUST BE SET
self.semester = semester # eg 'Fa2020'
self.timestamp = timestamp # datetime.datetime
self.bid_1_prep = 0
self.bid_2_prep = 0
self.bid_3_prep = 0
self.bid_4_prep = 0
self.bid_5_prep = 0
self.sect_bids = [] # list of bids MUST BE indexed same as s!
self.min_acc_units = 12 # minimum number of units acceptable
self.max_acc_units = 18
self.min_des_units = 14 # minimum number of units desired
self.max_des_units = 16
def __repr__(self):
#line1 = 'user: {} index: {} semester: {} timestamp: {}\n'.format(self.user,
# self.index, self.semester, self.timestamp)
#line2 = 'preps: 1:{} 2:{} 3:{} 4:{} 5:{} min_acc_units: {}'.format()
return('user: {} index: {} semester: {} timestamp: {} \n'
'preps: 1:{} 2:{} 3:{} 4:{} 5:{} min_acc_units: {} '
'min_des_units: {} max_des_units: {} max_acc_units: {}'.format(
self.user, self.index, self.semester, self.timestamp,
self.bid_1_prep, self.bid_2_prep, self.bid_3_prep,
self.bid_4_prep, self.bid_5_prep, self.min_acc_units,
self.min_des_units, self.max_des_units,
self.max_acc_units))
class USchedOpt:
# List of sections chosen so far for one user
def __init__(self, index):
self.unit_total = 0
self.sects_bid = 0
self.units_bid = 0
self.preps_bid = 0
self.total_bid = 0 # simply total of sects, units, preps
self.knocking_adj_penalty = 0 # unnecessary? might want to keep track
self.s = [] # list of section indices (si)
self.courses = [] # len(self.courses) is number of preps
self.index = index # self's index in r; matches ub
self.done = False
def __repr__(self):
sects = ''
for si in self.s:
sects += str(s[si].course) + ' at ' + s[si].start.strftime('%I:%M %p')+' choice: '+str(s[si].choice)+\
' index: ' + str(si) + '\n'
user_name = User.query.filter_by(id=ub[self.index].user).first().username
return('{} sects_bid: {} units: {} units_bid: {} preps_bid: {} total_bid: {}\n{}'.format(
user_name, self.sects_bid, self.unit_total, self.units_bid, self.preps_bid, self.total_bid, sects))
def add(self, si):
self.unit_total += s[si].units
if self.unit_total >= ub[self.index].min_des_units and self.unit_total <= ub[self.index].max_des_units:
self.units_bid = 4
else:
self.units_bid = 0
self.sects_bid += ub[self.index].sect_bids[s[si].index]
if s[si].taken_by is not '':
self.knocking_adj_penalty += knocking_adj_penalty
if s[si].course not in self.courses:
self.courses.append(s[si].course)
if len(self.courses) == 1:
self.preps_bid = ub[self.index].bid_1_prep
elif len(self.courses) == 2:
self.preps_bid = ub[self.index].bid_2_prep
elif len(self.courses) == 3:
self.preps_bid = ub[self.index].bid_3_prep
elif len(self.courses) == 4:
self.preps_bid = ub[self.index].bid_4_prep
elif len(self.courses) == 5:
self.preps_bid = ub[self.index].bid_5_prep
self.total_bid = self.units_bid + self.sects_bid + self.preps_bid
self.s.append(si)
def remove(self, si):
self.unit_total -= s[si].units
if ( self.unit_total >= ub[self.index].min_des_units and
self.unit_total <= ub[self.index].max_des_units ):
self.units_bid = 4
else:
self.units_bid = 0
self.sects_bid -= ub[self.index].sect_bids[s[si].index]
if s[si].taken_by is not '':
self.knocking_adj_penalty -= knocking_adj_penalty
self.courses = []
i = 0
while i < len(self.s):
if self.s[i] == si:
self.s.pop(i) # remove it
elif s[self.s[i]].course not in self.courses:
self.courses.append(s[self.s[i]].course)
i += 1
if len(self.courses) == 1:
self.preps_bid = ub[self.index].bid_1_prep
elif len(self.courses) == 2:
self.preps_bid = ub[self.index].bid_2_prep
elif len(self.courses) == 3:
self.preps_bid = ub[self.index].bid_3_prep
elif len(self.courses) == 4:
self.preps_bid = ub[self.index].bid_4_prep
elif len(self.courses) == 5:
self.preps_bid = ub[self.index].bid_5_prep
self.total_bid = self.units_bid + self.sects_bid + self.preps_bid
# returns new value after s[si] is added,
# or None if new units > max_acc_units or if schedule conflict
def eval_if_added(self, si):
new_units = self.unit_total + s[si].units
if new_units > ub[self.index].max_acc_units:
return None
if s[si].MTWTh:
for my_si in self.s:
if ( (s[my_si].start <= s[si].start <= s[my_si].end) or
(s[my_si].start <= s[si].end <= s[my_si].end) ):
return None
elif s[si].MW:
for my_si in self.s:
if s[my_si].MW or s[my_si].MTWTh:
if ( (s[my_si].start <= s[si].start <= s[my_si].end) or
(s[my_si].start <= s[si].end <= s[my_si].end) ):
return None
elif s[si].TTh:
for my_si in self.s:
if s[my_si].TTh or s[my_si].MTWTh:
if ( (s[my_si].start <= s[si].start <= s[my_si].end) or
(s[my_si].start <= s[si].end <= s[my_si].end) ):
return None
if ( new_units >= ub[self.index].min_des_units and
new_units <= ub[self.index].max_des_units ):
new_tot = 4
else:
new_tot = 0
new_tot += ub[self.index].sect_bids[si] # additional sect bid
if s[si].taken_by is not '':
new_tot -= knocking_adj_penalty
new_tot += self.sects_bid # old sects_bid
if s[si].course in self.courses:
new_tot += self.preps_bid # preps_bid is unchanged
else:
preps = len(self.courses) + 1
if preps == 1:
new_tot += ub[self.index].bid_1_prep
elif preps == 2:
new_tot += ub[self.index].bid_2_prep
elif preps == 3:
new_tot += ub[self.index].bid_3_prep
elif preps == 4:
new_tot += ub[self.index].bid_4_prep
elif preps == 5:
new_tot += ub[self.index].bid_5_prep
return new_tot
# returns change in total value if user
# trades si_old for si_new, or None if too many units or schedule conflict
def eval_trade(self, si_old, si_new):
new_units = self.unit_total - s[si_old].units + s[si_new].units
if new_units > ub[self.index].max_acc_units:
return None
if s[si_new].MTWTh:
for my_si in self.s:
if s[my_si].index != si_old:
if ( (s[my_si].start <= s[si_new].start <= s[my_si].end) or
(s[my_si].start <= s[si_new].end <= s[my_si].end) ):
return None
elif s[si_new].MW:
for my_si in self.s:
if s[my_si].index != si_old:
if s[my_si].MW or s[my_si].MTWTh:
if ( (s[my_si].start <= s[si_new].start <= s[my_si].end) or
(s[my_si].start <= s[si_new].end <= s[my_si].end) ):
return None
elif s[si_new].TTh:
for my_si in self.s:
if s[my_si].index != si_old:
if s[my_si].TTh or s[my_si].MTWTh:
if ( (s[my_si].start <= s[si_new].start <= s[my_si].end) or
(s[my_si].start <= s[si_new].end <= s[my_si].end) ):
return None
if ( new_units >= ub[self.index].min_des_units and
new_units <= ub[self.index].max_des_units ):
new_tot = 4
else:
new_tot = 0
new_tot += self.sects_bid - ub[self.index].sect_bids[si_old] + ub[self.index].sect_bids[si_new]
if s[si_new].taken_by is not '':
new_tot -= knocking_adj_penalty
if s[si_old].taken_by is not '':
new_tot += knocking_adj_penalty
new_courses = [s[si_new].course]
for my_si in self.s:
if s[my_si].index != si_old and s[my_si].course not in new_courses:
new_courses.append(s[my_si].course)
if len(new_courses) == 1:
new_tot += ub[self.index].bid_1_prep
elif len(new_courses) == 2:
new_tot += ub[self.index].bid_2_prep
elif len(new_courses) == 3:
new_tot += ub[self.index].bid_3_prep
elif len(new_courses) == 4:
new_tot += ub[self.index].bid_4_prep
elif len(new_courses) == 5:
new_tot += ub[self.index].bid_5_prep
return new_tot - self.total_bid
def load_sects(semester):
global s
sects = Section.query.filter_by(semester=semester).order_by(Section.choice_num).all()
# s_length = max([j.choice_num for j in sects + 1])
s = []
i = 0
skip = False
for x in sects:
for np in non_participants:
if x.taken_by.lower().strip()[0:5] == np[0:5]:
skip = True
if skip:
skip = False
continue
t = Sect(choice=x.choice_num, course=x.course, start=x.start_time,
end=x.end_time, MW=x.mon_wed, TTh=x.tue_thu, MTWTh=x.mtwth,
taken_by=x.taken_by.strip(), units=x.units, room=x.room)
t.index = i
i += 1
s.append(t)
# load round 1 user bids from db into ub
# assuming non_participants don't have bids in db and
# there are no bids on non_participant's classes!
def load_ub(semester):
global ub
ub = []
bids = UserBids.query.filter_by(primary=True).all()
i = 0
# length of sect_bids
sb_length = max([s.choice_num for s in Section.query.filter_by(
semester=semester).all()]) + 1
for b in bids:
if b.primary:
t = UBids(user=b.user_id, semester=semester, timestamp=b.timestamp)
t.index = i
i += 1
t.bid_1_prep = b.bid_1_prep
t.bid_2_prep = b.bid_2_prep
t.bid_3_prep = b.bid_3_prep
t.bid_4_prep = b.bid_4_prep
t.bid_5_prep = b.bid_5_prep
t.min_acc_units = b.min_acc_units
t.max_acc_units = b.max_acc_units
t.min_des_units = b.min_des_units
t.max_des_units = b.max_des_units
sbs = SectionBid.query.filter_by(user_bids_id=b.id).all()
t.sect_bids = [None for j in range(sb_length)]
for sb in sbs:
choice_num = Section.query.filter_by(id=sb.section_id).first().choice_num
t.sect_bids[choice_num] = sb.bid
# remove all Nones from list; should be in same order as s now
t.sect_bids = [x for x in t.sect_bids if x is not None]
ub.append(t)
def test_db_load():
for b in ub:
user_name = User.query.filter_by(id=b.user).first().username
db_ub_id = UserBids.query.filter_by(user_id=b.user, primary=True).first().id
sbs = SectionBid.query.filter_by(user_bids_id=db_ub_id).all()
for i in range(len(b.sect_bids)):
choice_num = s[i].choice
sect_id = Section.query.filter_by(choice_num=choice_num).first().id
db_bid = SectionBid.query.filter_by(section_id=sect_id, user_bids_id=db_ub_id).first().bid
if db_bid != b.sect_bids[i]:
print('Error! DB bid doesn\'t line up with ub bid!\
User: {}, sect index: {}, Choice: {}, DB Bid: {}, \
b.sect_bid: {}'.format(user_name, i, choice_num,
db_bid, b.sect_bids[i]))
def remove_bids_on_non_participants_sections():
count = 0
for sec in Section.query.all():
for np in non_participants:
if sec.taken_by.lower().strip()[0:5] == np[0:5]:
deletos = SectionBid.query.filter_by(section_id=sec.id).all()
for d in deletos:
db.session.delete(d)
count += 1
print('removed ', count, ' section bids!')
db.session.commit()
# r is a schedule, ie a list of USchedOpts
# returns the USchedOpt.index (user index in r, ub) of the owner of s[si]
# returns None if it's unclaimed, and -1 if it's taken by adjunct
def find_owner(r, si):
for u in r:
if si in u.s:
return u.index
if s[si].taken_by is not '':
return -1
return None
ub = [] # global list of user_bids
results = [] # global list of lists of USchedOpts result;
# each row is one schedule
# each schedule is a list of USchedOpts indexed by user_bids.index
# results[schedoption][user] is one USchedOpt
#r = [] # current USchedOpts for putting in results; indexed like ub
nv = [] # nv[sect.index][user.index] = new value after adding sect
s = [] # global list of sects; each sect's index
# MUST line up with the bids in each UBids.sect_bids
load_ub(semester)
load_sects(semester)
test_db_load()
order = orderer(len(ub))
for o in order:
o.extend(o[::-1]) # adds a reversed copy of o to o
o.extend(o) # doubles o
o.extend(o) # again
o.extend(o) # again; o is long enough for 16 choices
adjuncts_knocked = 0 # for testing
for o in order:
done = 0 # count of USchedOpts in r that are done
nv = [[None for b in ub] for sect in s]
r = [USchedOpt(i) for i in range(len(ub))]
for m in range(len(s)):
for n in range(len(ub)):
nv[m][n] = r[n].eval_if_added(m)
for i in o: # for each faculty in order, get sect with max new value
if not r[i].done:
if r[i].unit_total < ub[i].min_acc_units:
mode = 0 # definitely add a class!
elif r[i].unit_total < ub[i].min_des_units:
mode = 1 # only add a class if it increases value
elif r[i].unit_total <= ub[i].max_des_units:
mode = 2 # only add a class if it increases value by more than 1?
all_nv_are_none = True
max_nv = -20
for m in range(len(s)): # get sect w/ maximum new value
if nv[m][i] is not None:
all_nv_are_none = False
if nv[m][i] > max_nv:
if ( mode == 0 or (mode == 1 and nv[m][i] > r[i].total_bid) or
(mode == 2 and nv[m][i] > (r[i].total_bid + 1)) ):
max_nv = nv[m][i]
max_sec = m
if all_nv_are_none or max_nv == -20:
# there is no section that can legally and gainfully be added
r[i].done = True
else:
r[i].add(max_sec)
if s[max_sec].taken_by is not '':
adjuncts_knocked += 1
for n in range(len(ub)):
nv[max_sec][n] = None
for m in range(len(s)):
if nv[m][i] is not None: # only eval legal sects
nv[m][i] = r[i].eval_if_added(m)
if r[i].done:
done += 1
if done == len(r):
break
results.append(r)
totals = [0 for i in range(len(results))]
for i in range(len(results)):
for j in range(len(results[i])):
totals[i] += results[i][j].total_bid
totals[i] = totals[i]/len(results[i])
sumi = 0
for i in totals:
sumi += i
print('Averages of each schedule: ', totals)
print('Average pre-trade bid in schedules: ', str(sumi/len(totals)))
print('Average number of adjuncts knocked: ', str(adjuncts_knocked/len(results)))
test_results_strs = []
for i in range(len(results[13])):
test_results_strs.append(str(results[13][i]))
for z in range(1):
wtables = [] # list of want tables, one for each r in results. Each want table is
# a list, indexed like s, of wants. Each want
# is a list of tuples, (wanted sect, how much it's wanted)
for r in results:
wt = [[] for m in range(len(s))]
claimed = [] # list of si's claimed by non-adjunct faculty
unclaimed = [] # list of si's claimed by noone
adjuncts = [] # list of si's claimed by adjuncts; blocked from trades
owners = [None for si in range(len(s))]
for m in range(len(s)):
owner = find_owner(r=r, si=m)
owners[m] = owner
if owner is None:
unclaimed.append(m)
elif owner == -1:
adjuncts.append(m)
else:
claimed.append(m)
for m in range(len(s)):
if owners[m] is None: # un-owned classes can be traded, w/ 0 AV to non-owner
for c in claimed:
wt[m].append((c, 0))
elif owners[m] != -1: # si[m] is claimed; find and sort trades
for n in range(len(s)):
if owners[n] != -1: # no offers for adjuncts' classes
av = r[owners[m]].eval_trade(si_old=m, si_new=n)
if av is not None:
if av >= 0:
wt[m].append((n, av))
for x in range(len(wt[m])): # selection sort
index_of_max = x
for y in range(x + 1, len(wt[m])):
if wt[m][y][1] > wt[m][x][1]:
index_of_max = y
temp = wt[m][x]
wt[m][x] = wt[m][index_of_max]
wt[m][index_of_max] = temp
wtables.append(wt)
disjoint_sets = cycler.cycler(wt)
max_improvement = 0
max_index = None
for ds in range(len(disjoint_sets)): # TODO: move this code into cycler for abstraction
improvement = 0
for cyc in disjoint_sets[ds]:
improvement += cyc.value
if improvement > max_improvement:
max_improvement = improvement
max_index = ds
if max_index is not None:
for cyc in disjoint_sets[max_index]:
if owners[cyc.end.data] is not None:
r[owners[cyc.end.data]].add(cyc.start.data)
r[owners[cyc.end.data]].remove(cyc.end.data)
current = cyc.end
# give end's owner section owned by start
while current.prev_node is not None: # while current != start
# give current.prev's owner current's section
if owners[current.prev_node.data] is not None:
r[owners[current.prev_node.data]].add(current.data)
r[owners[current.prev_node.data]].remove(current.prev_node.data)
current = current.prev_node
totals = [0 for i in range(len(results))]
for i in range(len(results)):
for j in range(len(results[i])):
totals[i] += results[i][j].total_bid
totals[i] = totals[i]/len(results[i])
sumi = 0
for i in totals:
sumi += i
print('Averages of each schedule: ', totals)
print('Average bid after trading {} time in schedules: '.format(z+1), str(sumi/len(totals)))
#TESTING TRADES
# Note this test doesn't work! it prints the POST-TRADE wants instead of pre-trade wants.
# Fix later by making separate results list to compare before/after
test_wt_strs = ['' for m in range(len(results[13]))]
for m in range(len(results[13])):
print(ub[m])
print(test_results_strs[m])
for i in range(len(results[13][m].s)):
test_wt_strs[m] += 'si ' + str(results[13][m].s[i]) + ' wants: ' + str(wtables[13][results[13][m].s[i]]) + '\n'
print(test_wt_strs[m])
print(results[13][m])
############################################
#Code below inputs sample schedule into database!
############################################
'''sample_file = open('sample_schedule.csv')
reader = csv.reader(sample_file)
sem = 'Fa2019'
sect_list = []
for row in reader:
MW = row[4] == 'MW'
TTh = row[4] == 'TTh'
MTWTh = row[4] == 'MTWTh'
sect_list.append(sect(choice=int(row[0]), course=row[1],
start=datetime.datetime.time(datetime.datetime.strptime(row[2], '%I:%M %p')),
end=datetime.datetime.time(datetime.datetime.strptime(row[3], '%I:%M %p')),
MW=MW, TTh=TTh, MTWTh=MTWTh, taken_by=row[5],
units=int(row[6]), room=row[7]))
for sec in sect_list:
print(sec.choice, sec.course,
sec.start.strftime('%I:%M %p'),
sec.end.strftime('%I:%M %p'),
#datetime.time.strftime('%I:%M %p', sec.start),
#datetime.time.strftime('%I:%M %p', sec.end),
sec.MW, sec.TTh, sec.MTWTh, sec.taken_by, sec.units, sec.room)
for sec in sect_list:
s = Section(choice_num=sec.choice, start_time=sec.start, end_time=sec.end,
mon_wed=sec.MW, tue_thu=sec.TTh, mtwth=sec.MTWTh,
course=sec.course, room=sec.room, units=sec.units,
semester=sem, taken_by=sec.taken_by)
db.session.add(s)
db.session.commit()'''
#############################################
# Code below inputs test_r1_bids into database!
############################################
'''from test_r1_bids import b # list of user_bids
for u in b:
user_ref = User.query.filter_by(username=u.user).first()
ub = UserBids(bidder=user_ref, primary=True, timestamp=u.timestamp,
bid_1_prep=u.bid_1_prep, bid_2_prep=u.bid_2_prep,
bid_3_prep=u.bid_3_prep, bid_4_prep=u.bid_4_prep, bid_5_prep=u.bid_5_prep,
min_acc_units=u.min_acc_units, max_acc_units=u.max_acc_units,
min_des_units=u.min_des_units, max_des_units=u.max_des_units)
db.session.add(ub)
db.session.commit()'''
'''for u in b:
print(u.user,u.bid_3_prep,len(u.sect_bids))
user_id = User.query.filter_by(username=u.user).first().id
print('user_id: ', user_id)
ub_ref = UserBids.query.filter_by(user_id=user_id,primary=True).first()
print('ub_ref: ', ub_ref)
for x in u.sect_bids:
sect_ref = Section.query.filter_by(choice_num=x[0]).first()
#print('sect_ref: ', sect_ref, ' bid: ', x[1])
sb = SectionBid(bid=x[1], from_userbids=ub_ref, sect=sect_ref)
db.session.add(sb)
db.session.commit()'''