|
|
@@ -199,6 +199,207 @@ DISTRICT_DATA = {
|
|
199
|
199
|
"expected_local_total": 3529,
|
|
200
|
200
|
"expected_outside_total": 310,
|
|
201
|
201
|
},
|
|
|
202
|
+ 4: {
|
|
|
203
|
+ "name": "静安区",
|
|
|
204
|
+ "local": [
|
|
|
205
|
+ (25, "上海市市西中学", 79),
|
|
|
206
|
+ (28, "上海市市北中学", 86),
|
|
|
207
|
+ (26, "上海市育才中学", 91),
|
|
|
208
|
+ (27, "上海市新中高级中学", 79),
|
|
|
209
|
+ (30, "上海市第六十中学", 66),
|
|
|
210
|
+ (31, "上海市华东模范中学", 49),
|
|
|
211
|
+ (29, "上海市回民中学", 68),
|
|
|
212
|
+ (101, "上海市民立中学", 280),
|
|
|
213
|
+ (102, "上海市第一中学", 200),
|
|
|
214
|
+ (103, "上海市风华中学", 380),
|
|
|
215
|
+ (104, "上海市彭浦中学", 304),
|
|
|
216
|
+ (106, "上海市闸北第八中学", 228),
|
|
|
217
|
+ (105, "上海市久隆模范中学", 50, "(收费生)", None),
|
|
|
218
|
+ (105, "上海市久隆模范中学", 77),
|
|
|
219
|
+ (107, "同济大学附属七一中学", 160),
|
|
|
220
|
+ (1023, "复旦附中静安高级中学", 45),
|
|
|
221
|
+ (100, "上海戏剧学院附属高级中学", 80, "", None),
|
|
|
222
|
+ (
|
|
|
223
|
+ 100,
|
|
|
224
|
+ "上海戏剧学院附属高级中学",
|
|
|
225
|
+ 10,
|
|
|
226
|
+ "(艺术班)",
|
|
|
227
|
+ "只招收经学校艺术特长测试合格的学生。",
|
|
|
228
|
+ ),
|
|
|
229
|
+ (109, "上海市向东中学", 240),
|
|
|
230
|
+ (110, "上海大学市北附属中学", 240),
|
|
|
231
|
+ (108, "上海田家炳中学", 72),
|
|
|
232
|
+ (111, "上海市民办扬波中学", 103),
|
|
|
233
|
+ (112, "上海市民办新和中学(停招)", 0),
|
|
|
234
|
+ (113, "上海市民办风范中学", 163),
|
|
|
235
|
+ ],
|
|
|
236
|
+ "outside": [
|
|
|
237
|
+ (1, "上海市上海中学", 1),
|
|
|
238
|
+ (4, "华东师范大学第二附属中学", 1),
|
|
|
239
|
+ (3, "复旦大学附属中学", 1),
|
|
|
240
|
+ (2, "上海交通大学附属中学", 2),
|
|
|
241
|
+ (81, "上海市同济黄浦设计创意中学", 1),
|
|
|
242
|
+ (87, "上海市民办西南高级中学", 2),
|
|
|
243
|
+ (117, "上海音乐学院附属安师实验中学", 7),
|
|
|
244
|
+ (122, "上海安生学校", 3),
|
|
|
245
|
+ (148, "上海市文来中学", 2),
|
|
|
246
|
+ (156, "上海市民办燎原双语高级中学", 2),
|
|
|
247
|
+ (153, "上海市民办文绮中学", 1),
|
|
|
248
|
+ (176, "上海宝山区世外学校", 4),
|
|
|
249
|
+ (180, "上海市宝山华曜高级中学", 1),
|
|
|
250
|
+ (177, "上海存志高级中学", 4),
|
|
|
251
|
+ (178, "上海宝山区民办维尚高级中学", 1),
|
|
|
252
|
+ (179, "上海创艺高级中学", 2),
|
|
|
253
|
+ (851, "上海民办行中中学", 2),
|
|
|
254
|
+ (175, "上海市同洲模范学校", 1),
|
|
|
255
|
+ (852, "上海金瑞学校", 1),
|
|
|
256
|
+ (189, "上海华旭双语学校", 2),
|
|
|
257
|
+ (267, "上海美达菲双语高级中学", 1),
|
|
|
258
|
+ (190, "上海嘉定区民办华盛怀少学校", 1),
|
|
|
259
|
+ (230, "上海市民办尚德实验学校", 4),
|
|
|
260
|
+ (229, "上海浦东新区民办东鼎外国语学校", 1),
|
|
|
261
|
+ (220, "上海市民办丰华高级中学", 1),
|
|
|
262
|
+ (218, "上海市浦东新区民办浦实高级中学", 2),
|
|
|
263
|
+ (223, "民办上海工商外国语职业学院附属中学", 1),
|
|
|
264
|
+ (244, "上海金山区世外学校", 4),
|
|
|
265
|
+ (246, "上海市民办永昌中学", 1),
|
|
|
266
|
+ (243, "上海市民办交大南洋中学", 3),
|
|
|
267
|
+ (254, "上海赫贤学校", 4),
|
|
|
268
|
+ (251, "上海市西外外国语学校", 4),
|
|
|
269
|
+ (859, "上海市松江区科德高级中学", 1),
|
|
|
270
|
+ (1034, "上海市松江区励滕高级中学", 1),
|
|
|
271
|
+ (995, "上海松江区爱菊学校", 2),
|
|
|
272
|
+ (863, "上海青浦区世外高级中学", 2),
|
|
|
273
|
+ (260, "上海青浦区协和双语学校", 5),
|
|
|
274
|
+ (862, "上海青浦区宏润博源高级中学", 1),
|
|
|
275
|
+ (272, "上海民办民一中学", 20),
|
|
|
276
|
+ ],
|
|
|
277
|
+ "expected_local_total": 3150,
|
|
|
278
|
+ "expected_outside_total": 100,
|
|
|
279
|
+ },
|
|
|
280
|
+ 6: {
|
|
|
281
|
+ "name": "虹口区",
|
|
|
282
|
+ "local": [
|
|
|
283
|
+ (36, "复旦大学附属复兴中学", 86),
|
|
|
284
|
+ (37, "华东师范大学第一附属中学", 86),
|
|
|
285
|
+ (38, "上海财经大学附属北郊高级中学", 64),
|
|
|
286
|
+ (125, "上海音乐学院虹口区北虹高级中学", 270),
|
|
|
287
|
+ (124, "上海师范大学附属虹口中学", 340),
|
|
|
288
|
+ (126, "上海市继光高级中学", 262),
|
|
|
289
|
+ (128, "上海市鲁迅中学", 210),
|
|
|
290
|
+ (127, "同济大学附属澄衷中学", 270),
|
|
|
291
|
+ (129, "上海市第五十二中学", 280),
|
|
|
292
|
+ ],
|
|
|
293
|
+ "outside": [
|
|
|
294
|
+ (1, "上海市上海中学", 1),
|
|
|
295
|
+ (4, "华东师范大学第二附属中学", 1),
|
|
|
296
|
+ (3, "复旦大学附属中学", 1),
|
|
|
297
|
+ (2, "上海交通大学附属中学", 2),
|
|
|
298
|
+ (81, "上海市同济黄浦设计创意中学", 3),
|
|
|
299
|
+ (105, "上海市久隆模范中学", 1),
|
|
|
300
|
+ (108, "上海田家炳中学", 3),
|
|
|
301
|
+ (111, "上海市民办扬波中学", 1),
|
|
|
302
|
+ (113, "上海市民办风范中学", 5),
|
|
|
303
|
+ (100, "上海戏剧学院附属高级中学", 4),
|
|
|
304
|
+ (122, "上海安生学校", 2),
|
|
|
305
|
+ (117, "上海音乐学院附属安师实验中学", 1),
|
|
|
306
|
+ (851, "上海民办行中中学", 1),
|
|
|
307
|
+ (177, "上海存志高级中学", 2),
|
|
|
308
|
+ (178, "上海宝山区民办维尚高级中学", 1),
|
|
|
309
|
+ (179, "上海创艺高级中学", 1),
|
|
|
310
|
+ (180, "上海市宝山华曜高级中学", 3),
|
|
|
311
|
+ (175, "上海市同洲模范学校", 1),
|
|
|
312
|
+ (852, "上海金瑞学校", 1),
|
|
|
313
|
+ (176, "上海宝山区世外学校", 1),
|
|
|
314
|
+ (188, "上海市民办远东学校", 2),
|
|
|
315
|
+ (189, "上海华旭双语学校", 4),
|
|
|
316
|
+ (190, "上海嘉定区民办华盛怀少学校", 4),
|
|
|
317
|
+ (220, "上海市民办丰华高级中学", 1),
|
|
|
318
|
+ (228, "上海市民办金苹果学校", 1),
|
|
|
319
|
+ (229, "上海浦东新区民办东鼎外国语学校", 1),
|
|
|
320
|
+ (230, "上海市民办尚德实验学校", 3),
|
|
|
321
|
+ (243, "上海市民办交大南洋中学", 2),
|
|
|
322
|
+ (246, "上海市民办永昌中学", 2),
|
|
|
323
|
+ (244, "上海金山区世外学校", 2),
|
|
|
324
|
+ (860, "上海领科双语学校", 1),
|
|
|
325
|
+ (251, "上海市西外外国语学校", 3),
|
|
|
326
|
+ (254, "上海赫贤学校", 1),
|
|
|
327
|
+ (863, "上海青浦区世外高级中学", 1),
|
|
|
328
|
+ (862, "上海青浦区宏润博源高级中学", 1),
|
|
|
329
|
+ (259, "上海宋庆龄学校", 1),
|
|
|
330
|
+ (260, "上海青浦区协和双语学校", 1),
|
|
|
331
|
+ (267, "上海美达菲双语高级中学", 1),
|
|
|
332
|
+ (266, "上海奉贤区博华高级中学", 1),
|
|
|
333
|
+ (268, "上海市崇明区城桥中学", 2),
|
|
|
334
|
+ (272, "上海民办民一中学", 8),
|
|
|
335
|
+ ],
|
|
|
336
|
+ "expected_local_total": 1868,
|
|
|
337
|
+ "expected_outside_total": 79,
|
|
|
338
|
+ },
|
|
|
339
|
+ 7: {
|
|
|
340
|
+ "name": "杨浦区",
|
|
|
341
|
+ "local": [
|
|
|
342
|
+ (40, "上海市控江中学", 120),
|
|
|
343
|
+ (39, "上海市杨浦高级中学", 123),
|
|
|
344
|
+ (41, "同济大学第一附属中学", 78),
|
|
|
345
|
+ (132, "上海理工大学附属中学", 300),
|
|
|
346
|
+ (133, "上海市市东实验学校(上海市市东中学)", 380),
|
|
|
347
|
+ (134, "上海财经大学附属中学", 396),
|
|
|
348
|
+ (137, "上海市复旦实验中学", 315),
|
|
|
349
|
+ (135, "上海市同济中学", 315),
|
|
|
350
|
+ (136, "上海市中原中学", 315),
|
|
|
351
|
+ (138, "上海理工大学附属杨浦少云中学", 225),
|
|
|
352
|
+ (139, "上海市民星中学", 270),
|
|
|
353
|
+ (140, "上海体育大学附属中学", 84),
|
|
|
354
|
+ (142, "上海市民办上实剑桥外国语中学", 140),
|
|
|
355
|
+ ],
|
|
|
356
|
+ "outside": [
|
|
|
357
|
+ (1, "上海市上海中学", 1),
|
|
|
358
|
+ (4, "华东师范大学第二附属中学", 1),
|
|
|
359
|
+ (3, "复旦大学附属中学", 1),
|
|
|
360
|
+ (2, "上海交通大学附属中学", 1),
|
|
|
361
|
+ (105, "上海市久隆模范中学", 1),
|
|
|
362
|
+ (268, "上海市崇明区城桥中学", 3),
|
|
|
363
|
+ (271, "上海市崇明区堡镇中学", 6),
|
|
|
364
|
+ (100, "上海戏剧学院附属高级中学", 8),
|
|
|
365
|
+ (117, "上海音乐学院附属安师实验中学", 4),
|
|
|
366
|
+ (81, "上海市同济黄浦设计创意中学", 2),
|
|
|
367
|
+ (108, "上海田家炳中学", 2),
|
|
|
368
|
+ (113, "上海市民办风范中学", 5),
|
|
|
369
|
+ (122, "上海安生学校", 6),
|
|
|
370
|
+ (156, "上海市民办燎原双语高级中学", 1),
|
|
|
371
|
+ (851, "上海民办行中中学", 3),
|
|
|
372
|
+ (177, "上海存志高级中学", 28),
|
|
|
373
|
+ (178, "上海宝山区民办维尚高级中学", 3),
|
|
|
374
|
+ (179, "上海创艺高级中学", 8),
|
|
|
375
|
+ (180, "上海市宝山华曜高级中学", 2),
|
|
|
376
|
+ (175, "上海市同洲模范学校", 8),
|
|
|
377
|
+ (852, "上海金瑞学校", 5),
|
|
|
378
|
+ (176, "上海宝山区世外学校", 1),
|
|
|
379
|
+ (188, "上海市民办远东学校", 2),
|
|
|
380
|
+ (189, "上海华旭双语学校", 5),
|
|
|
381
|
+ (190, "上海嘉定区民办华盛怀少学校", 7),
|
|
|
382
|
+ (220, "上海市民办丰华高级中学", 1),
|
|
|
383
|
+ (223, "民办上海工商外国语职业学院附属中学", 2),
|
|
|
384
|
+ (228, "上海市民办金苹果学校", 1),
|
|
|
385
|
+ (229, "上海浦东新区民办东鼎外国语学校", 1),
|
|
|
386
|
+ (230, "上海市民办尚德实验学校", 2),
|
|
|
387
|
+ (243, "上海市民办交大南洋中学", 15),
|
|
|
388
|
+ (246, "上海市民办永昌中学", 1),
|
|
|
389
|
+ (244, "上海金山区世外学校", 1),
|
|
|
390
|
+ (255, "上海市松江九峰实验学校", 1),
|
|
|
391
|
+ (251, "上海市西外外国语学校", 5),
|
|
|
392
|
+ (863, "上海青浦区世外高级中学", 5),
|
|
|
393
|
+ (862, "上海青浦区宏润博源高级中学", 4),
|
|
|
394
|
+ (259, "上海宋庆龄学校", 1),
|
|
|
395
|
+ (260, "上海青浦区协和双语学校", 2),
|
|
|
396
|
+ (267, "上海美达菲双语高级中学", 1),
|
|
|
397
|
+ (266, "上海奉贤区博华高级中学", 2),
|
|
|
398
|
+ (272, "上海民办民一中学", 23),
|
|
|
399
|
+ ],
|
|
|
400
|
+ "expected_local_total": 3061,
|
|
|
401
|
+ "expected_outside_total": 182,
|
|
|
402
|
+ },
|
|
202
|
403
|
9: {
|
|
203
|
404
|
"name": "宝山区",
|
|
204
|
405
|
"local": [
|
|
|
@@ -275,6 +476,15 @@ SPECIAL_REMARKS = {
|
|
275
|
476
|
}
|
|
276
|
477
|
|
|
277
|
478
|
|
|
|
479
|
+def unpack_source_row(row):
|
|
|
480
|
+ school_id, school_name, plan_num = row[:3]
|
|
|
481
|
+ if len(row) == 5:
|
|
|
482
|
+ remark, remark2 = row[3:]
|
|
|
483
|
+ else:
|
|
|
484
|
+ remark, remark2 = SPECIAL_REMARKS.get(school_id, ("", None))
|
|
|
485
|
+ return school_id, school_name, plan_num, remark, remark2
|
|
|
486
|
+
|
|
|
487
|
+
|
|
278
|
488
|
def connect():
|
|
279
|
489
|
return pymysql.connect(
|
|
280
|
490
|
**DB_CONFIG,
|
|
|
@@ -284,9 +494,14 @@ def connect():
|
|
284
|
494
|
|
|
285
|
495
|
|
|
286
|
496
|
def validate_source_data(district_id, data):
|
|
287
|
|
- local_total = sum(plan_num for _, _, plan_num in data["local"])
|
|
288
|
|
- outside_total = sum(plan_num for _, _, plan_num in data["outside"])
|
|
289
|
|
- all_ids = [school_id for school_id, _, _ in data["local"] + data["outside"]]
|
|
|
497
|
+ local_total = sum(row[2] for row in data["local"])
|
|
|
498
|
+ outside_total = sum(row[2] for row in data["outside"])
|
|
|
499
|
+ all_keys = [
|
|
|
500
|
+ (school_id, remark)
|
|
|
501
|
+ for school_id, _, _, remark, _ in map(
|
|
|
502
|
+ unpack_source_row, data["local"] + data["outside"]
|
|
|
503
|
+ )
|
|
|
504
|
+ ]
|
|
290
|
505
|
|
|
291
|
506
|
if local_total != data["expected_local_total"]:
|
|
292
|
507
|
raise ValueError(
|
|
|
@@ -298,15 +513,18 @@ def validate_source_data(district_id, data):
|
|
298
|
513
|
f"{data['name']} outside total: expected "
|
|
299
|
514
|
f"{data['expected_outside_total']}, got {outside_total}"
|
|
300
|
515
|
)
|
|
301
|
|
- if len(all_ids) != len(set(all_ids)):
|
|
302
|
|
- raise ValueError(f"{data['name']} contains duplicate school IDs")
|
|
|
516
|
+ if len(all_keys) != len(set(all_keys)):
|
|
|
517
|
+ raise ValueError(f"{data['name']} contains duplicate school/remark keys")
|
|
303
|
518
|
if district_id < 1 or district_id > 16:
|
|
304
|
519
|
raise ValueError(f"invalid DistrictID: {district_id}")
|
|
305
|
520
|
|
|
306
|
521
|
|
|
307
|
522
|
def load_and_validate_schools(cursor, data):
|
|
308
|
523
|
source = data["local"] + data["outside"]
|
|
309
|
|
- expected = {school_id: school_name for school_id, school_name, _ in source}
|
|
|
524
|
+ expected = {
|
|
|
525
|
+ school_id: school_name
|
|
|
526
|
+ for school_id, school_name, _, _, _ in map(unpack_source_row, source)
|
|
|
527
|
+ }
|
|
310
|
528
|
placeholders = ", ".join(["%s"] * len(expected))
|
|
311
|
529
|
cursor.execute(
|
|
312
|
530
|
f"""
|
|
|
@@ -356,8 +574,8 @@ def load_previous_plan_nums(cursor, district_id):
|
|
356
|
574
|
|
|
357
|
575
|
def build_records(district_id, data, schools, previous_plan_nums):
|
|
358
|
576
|
records = []
|
|
359
|
|
- for school_id, _, plan_num in data["local"] + data["outside"]:
|
|
360
|
|
- remark, remark2 = SPECIAL_REMARKS.get(school_id, ("", None))
|
|
|
577
|
+ for source_row in data["local"] + data["outside"]:
|
|
|
578
|
+ school_id, _, plan_num, remark, remark2 = unpack_source_row(source_row)
|
|
361
|
579
|
previous = previous_plan_nums.get((school_id, remark), 0)
|
|
362
|
580
|
records.append(
|
|
363
|
581
|
{
|
|
|
@@ -482,14 +700,14 @@ def print_summary(district_id, data, records):
|
|
482
|
700
|
"rows",
|
|
483
|
701
|
len(data["local"]),
|
|
484
|
702
|
"plan",
|
|
485
|
|
- sum(plan_num for _, _, plan_num in data["local"]),
|
|
|
703
|
+ sum(row[2] for row in data["local"]),
|
|
486
|
704
|
)
|
|
487
|
705
|
print(
|
|
488
|
706
|
"outside",
|
|
489
|
707
|
"rows",
|
|
490
|
708
|
len(data["outside"]),
|
|
491
|
709
|
"plan",
|
|
492
|
|
- sum(plan_num for _, _, plan_num in data["outside"]),
|
|
|
710
|
+ sum(row[2] for row in data["outside"]),
|
|
493
|
711
|
)
|
|
494
|
712
|
for row in records:
|
|
495
|
713
|
print(
|