Refactorize debug and warning functions
add switches to control optimization
This commit is contained in:
parent
67bab0af54
commit
474d2dffbd
219
get.py
219
get.py
@ -6,6 +6,7 @@ import csv
|
||||
import json
|
||||
import os
|
||||
import pdb # used for debugging
|
||||
import inspect # used for debugging
|
||||
import random
|
||||
import sys
|
||||
|
||||
@ -26,6 +27,33 @@ def die(msg: str, status=3):
|
||||
sys.exit(status)
|
||||
|
||||
|
||||
def debug(*args):
|
||||
if not hasattr(debug, "counter"):
|
||||
debug.counter = 1 # Initialize the counter if it doesn't exist
|
||||
else:
|
||||
debug.counter += 1
|
||||
caller_frame = inspect.currentframe().f_back
|
||||
where = str(caller_frame.f_lineno) + "@" + caller_frame.f_code.co_name
|
||||
if len(args) > 0:
|
||||
print(f"[DEBUG {debug.counter}:{where}] " + str(args[0]), args[1:])
|
||||
else:
|
||||
print(f"[DEBUG {debug.counter}:{where}] (no reason given)")
|
||||
|
||||
|
||||
def warning(*args):
|
||||
if len(args) > 0:
|
||||
print("[WARNING] " + str(args[0]), args[1:])
|
||||
else:
|
||||
print("[WARNING] (no reason given)")
|
||||
|
||||
|
||||
def info(*args):
|
||||
if len(args) > 0:
|
||||
print("[INFO] " + str(args[0]), args[1:])
|
||||
else:
|
||||
print("[INFO] (no reason given)")
|
||||
|
||||
|
||||
load_dotenv(".env")
|
||||
|
||||
SCODOC_SERVER = os.environ.get("SCODOC_SERVER") or "http://localhost:5000"
|
||||
@ -39,7 +67,7 @@ SCODOC_PASSWORD = os.environ.get("SCODOC_PASSWORD") or die(
|
||||
API_URL = f"{SCODOC_SERVER}/ScoDoc/api"
|
||||
|
||||
# TODO : refactor globals
|
||||
debug = True # Not used
|
||||
DEBUG = True # Not used
|
||||
BLOCKING = True # Die if csv is incorrect
|
||||
|
||||
# TODO : refactor / put globals in a class, eg Config
|
||||
@ -47,7 +75,11 @@ depts = []
|
||||
orderkey = ""
|
||||
|
||||
|
||||
def blockordie(status=2):
|
||||
def blockordie(reason: str = "", status: int = 2):
|
||||
if reason:
|
||||
print(reason)
|
||||
else:
|
||||
print("Blocking, no reason given")
|
||||
if BLOCKING:
|
||||
sys.exit(status)
|
||||
|
||||
@ -66,17 +98,52 @@ def cli_check():
|
||||
|
||||
parser = argparse.ArgumentParser(description="Process some departments.")
|
||||
parser.add_argument("--techno", action="store_true", help="Enable TECHNO mode")
|
||||
parser.add_argument("depts", nargs="+", help="List of departments")
|
||||
parser.add_argument("depts", nargs="*", help="List of departments")
|
||||
parser.add_argument(
|
||||
"--base",
|
||||
"-b",
|
||||
type=int,
|
||||
choices=range(2000, 2667),
|
||||
choices=range(2000, 2067),
|
||||
default=2021,
|
||||
help="base year for the cohort (integer between 2000 and 2666)",
|
||||
)
|
||||
|
||||
optimize_group = parser.add_mutually_exclusive_group()
|
||||
optimize_group.add_argument(
|
||||
"--reuse", action="store_true", help="Reuse mode, sets value to 0"
|
||||
)
|
||||
optimize_group.add_argument(
|
||||
"--optimize",
|
||||
type=str,
|
||||
nargs="?",
|
||||
const="100", # Default value if --optimize is used without specifying n
|
||||
help="Optimize mode, takes an optional integer (default is 100, or 300 if no optimization option specified)",
|
||||
)
|
||||
optimize_group.add_argument(
|
||||
"--restart",
|
||||
type=str,
|
||||
nargs="?",
|
||||
const="300", # Default value if --restart is used without specifying n
|
||||
help="Restart & Optimize mode, takes an optional integer (default is 300)",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
Options.restart = False
|
||||
if args.reuse:
|
||||
Options.optimize = 0
|
||||
elif args.restart is not None:
|
||||
Options.restart = True
|
||||
try:
|
||||
Options.optimize = -int(args.restart)
|
||||
except (TypeError, ValueError):
|
||||
Options.optimize = -300
|
||||
if args.restart:
|
||||
args.depts.insert(0, args.restart)
|
||||
else:
|
||||
try:
|
||||
Options.optimize = int(args.optimize)
|
||||
except (TypeError, ValueError):
|
||||
Options.optimize = 300
|
||||
if args.optimize:
|
||||
args.depts.insert(0, args.optimize)
|
||||
|
||||
Options.base_year = args.base
|
||||
Options.techno = args.techno
|
||||
@ -129,6 +196,8 @@ def conf_value(xkey: str):
|
||||
"year_separator": " ",
|
||||
"rank_separator": "",
|
||||
"diplome_separator": "",
|
||||
"reuse": "yes",
|
||||
"optimize": "yes",
|
||||
}
|
||||
if xkey in conf:
|
||||
return conf[xkey]
|
||||
@ -176,8 +245,7 @@ def read_theme():
|
||||
if len(row) == 0:
|
||||
continue
|
||||
elif len(row[0]) == 0:
|
||||
print("Wrong line in theme : " + str(row))
|
||||
blockordie()
|
||||
blockordie("Wrong line in theme : " + str(row))
|
||||
elif row[0][0] == "#":
|
||||
continue
|
||||
else:
|
||||
@ -210,8 +278,7 @@ def read_redirects():
|
||||
if len(row) == 0:
|
||||
continue
|
||||
elif len(row[0]) == 0:
|
||||
print("Wrong line in redirect : " + str(row))
|
||||
blockordie()
|
||||
blockordie("Wrong line in redirect : " + str(row))
|
||||
elif row[0][0] == "#":
|
||||
continue
|
||||
else:
|
||||
@ -227,7 +294,7 @@ token = None
|
||||
|
||||
|
||||
def get_json(url: str, params=None):
|
||||
print(f"Requesting {url}")
|
||||
debug(f"Requesting {url}")
|
||||
global token
|
||||
if token == None:
|
||||
url_token = f"{API_URL}/tokens"
|
||||
@ -237,18 +304,19 @@ def get_json(url: str, params=None):
|
||||
if response.status_code == 200:
|
||||
token = response.json().get("token")
|
||||
else:
|
||||
print(
|
||||
f"Erreur de récupération de token: {response.status_code} - {response.text}"
|
||||
blockordie(
|
||||
f"Erreur de récupération de token: {response.status_code} - {response.text}",
|
||||
status=1,
|
||||
)
|
||||
sys.exit(1)
|
||||
headers = {"Authorization": f"Bearer {token}"}
|
||||
response = requests.get(url, headers=headers, params=params)
|
||||
if response.status_code == 200:
|
||||
# Afficher la réponse JSON
|
||||
return response.json()
|
||||
else:
|
||||
print(f"Erreur avec {url}: {response.status_code} - {response.text}")
|
||||
sys.exit(1)
|
||||
blockordie(
|
||||
f"Erreur avec {url}: {response.status_code} - {response.text}", status=1
|
||||
)
|
||||
|
||||
|
||||
formsem_dept = {}
|
||||
@ -337,6 +405,8 @@ def get_override(sem, xkey, default=None):
|
||||
def nick_replace(
|
||||
department, diplome, rank, modalite, parcours, nick, year=Options.base_year
|
||||
):
|
||||
if type(rank) != int:
|
||||
rank = 0
|
||||
if len(department) > 0:
|
||||
nick = nick.replace(
|
||||
"{department}", conf_value("department_separator") + department
|
||||
@ -357,7 +427,7 @@ def nick_replace(
|
||||
nick = nick.replace("{diplomenobut}", conf_value("diplome_separator") + diplome)
|
||||
else:
|
||||
nick = nick.replace("{diplomenobut}", "")
|
||||
if len(str(rank)) > 0:
|
||||
if rank > 0:
|
||||
nick = nick.replace("{rank}", conf_value("rank_separator") + str(rank))
|
||||
else:
|
||||
nick = nick.replace("{rank}", "")
|
||||
@ -424,7 +494,6 @@ def analyse_student(semobj, etud, univ_year=None):
|
||||
modalite = None
|
||||
for g in goal:
|
||||
gg = g.split("=")
|
||||
# print(f"Looking for {gg[0]} yielding {gg[1]} out of {groupes}")
|
||||
if gg[0] in groups:
|
||||
modalite = gg[1]
|
||||
nick = conf_value("nick")
|
||||
@ -523,11 +592,11 @@ def analyse_depts():
|
||||
continue
|
||||
if bucket in studentsummary["cursus"]:
|
||||
semestreerreur = int(bucket) + 1
|
||||
print(
|
||||
warning(
|
||||
f"// Élève {etudid} dans deux semestres à la fois : S{semestreerreur}, semestres {studentsummary['cursus'][bucket]} et {semid}"
|
||||
)
|
||||
if "dept" in studentsummary and studentsummary["dept"] != dept:
|
||||
print(
|
||||
warning(
|
||||
f"// Élève ayant changé de département {dept},{studentsummary['dept']}"
|
||||
)
|
||||
# department, diplome, rank, modalite, parcours, nick = analyse_student(
|
||||
@ -1044,7 +1113,8 @@ def crossweight(node_position, node_layer, edges):
|
||||
return w
|
||||
|
||||
|
||||
def genetic_optimize(node_position, node_layer, edges):
|
||||
def genetic_optimize(node_position, node_layer, edges, loops=1):
|
||||
debug(f"Begin genetic optimization with {loops} loops")
|
||||
oldcandidates = []
|
||||
l_indices = list(range(5))
|
||||
lays = []
|
||||
@ -1055,6 +1125,7 @@ def genetic_optimize(node_position, node_layer, edges):
|
||||
for i in lays[index]:
|
||||
randomness_l.append(index)
|
||||
w = crossweight(node_position, node_layer, edges)
|
||||
|
||||
for i in range(20):
|
||||
oldcandidates.append([node_position.copy(), w])
|
||||
w = crossweight(node_position, node_layer, edges)
|
||||
@ -1070,7 +1141,7 @@ def genetic_optimize(node_position, node_layer, edges):
|
||||
k += 1
|
||||
oldcandidates.append([n, w])
|
||||
candidates = oldcandidates
|
||||
for i in range(300):
|
||||
for i in range(loops):
|
||||
oldcandidates = candidates
|
||||
oldcandidates.sort(key=lambda x: x[1])
|
||||
candidates = oldcandidates[:30]
|
||||
@ -1119,11 +1190,37 @@ def genetic_optimize(node_position, node_layer, edges):
|
||||
b = lays[i].copy()
|
||||
b.sort(key=lambda x: best[x])
|
||||
orders.append(b)
|
||||
print(orders)
|
||||
print(candidates[0][1])
|
||||
debug(orders)
|
||||
debug(candidates[0][1])
|
||||
return orders
|
||||
|
||||
|
||||
def ordernodes(layers, orders, edges):
|
||||
node_position = {}
|
||||
node_layer = {}
|
||||
newls = [[], [], [], [], []]
|
||||
if orders != {}:
|
||||
for i in range(len(newls)):
|
||||
ls = newls[i]
|
||||
for node in orders[i]:
|
||||
if node in layers[i]:
|
||||
ls.append(node)
|
||||
for node in layers[i]:
|
||||
if node not in ls:
|
||||
ls.append(node)
|
||||
for layer, layernodes in enumerate(newls):
|
||||
for j, n in enumerate(layernodes):
|
||||
node_position[n] = j
|
||||
node_layer[n] = layer
|
||||
else:
|
||||
for layer, layernodes in enumerate(layers):
|
||||
for j, n in enumerate(layernodes):
|
||||
node_position[n] = j
|
||||
node_layer[n] = layer
|
||||
debug(crossweight(node_position, node_layer, edges))
|
||||
return node_position, node_layer, newls
|
||||
|
||||
|
||||
def printsvg():
|
||||
padding = 4
|
||||
unit_ratio = 96 / 72
|
||||
@ -1164,64 +1261,31 @@ def printsvg():
|
||||
else:
|
||||
node_structure[startnode]["next"].append([endnode, weight])
|
||||
edges.append([startnode, endnode, weight])
|
||||
node_position = {}
|
||||
node_layer = {}
|
||||
layer_structure = [
|
||||
{"olayer": []},
|
||||
{"olayer": []},
|
||||
{"olayer": []},
|
||||
{"olayer": []},
|
||||
{"olayer": []},
|
||||
]
|
||||
|
||||
lastorders = read_conf("best-" + orderkey)
|
||||
if lastorders != {}:
|
||||
for i in range(5):
|
||||
ls = layer_structure[i]
|
||||
ord = lastorders[i]
|
||||
for node in lastorders[i]:
|
||||
if node in layers[i]:
|
||||
ls["olayer"].append(node)
|
||||
for node in layers[i]:
|
||||
if node not in ls["olayer"]:
|
||||
ls["olayer"].append(node)
|
||||
for layer, layernodes in enumerate(layer_structure):
|
||||
for j, n in enumerate(layernodes["olayer"]):
|
||||
node_position[n] = j
|
||||
node_layer[n] = layer
|
||||
print(crossweight(node_position, node_layer, edges))
|
||||
filename = "best-" + orderkey
|
||||
if Options.restart:
|
||||
try:
|
||||
os.remove(filename)
|
||||
except OSError:
|
||||
pass
|
||||
if Options.optimize >= 0:
|
||||
lastorders = read_conf(filename)
|
||||
else:
|
||||
for layer, layernodes in enumerate(layers):
|
||||
for j, n in enumerate(layernodes):
|
||||
node_position[n] = j
|
||||
node_layer[n] = layer
|
||||
orders = genetic_optimize(node_position, node_layer, edges)
|
||||
lastorders = {}
|
||||
node_position, node_layer, newls = ordernodes(layers, lastorders, edges)
|
||||
if Options.optimize != 0:
|
||||
orders = genetic_optimize(
|
||||
node_position, node_layer, edges, loops=abs(Options.optimize)
|
||||
)
|
||||
else:
|
||||
orders = newls
|
||||
write_conf("best-" + orderkey, orders)
|
||||
layer_structure = [
|
||||
{"olayer": []},
|
||||
{"olayer": []},
|
||||
{"olayer": []},
|
||||
{"olayer": []},
|
||||
{"olayer": []},
|
||||
]
|
||||
for i in range(5):
|
||||
ls = layer_structure[i]
|
||||
ord = orders[i]
|
||||
for node in orders[i]:
|
||||
if node in layers[i]:
|
||||
ls["olayer"].append(node)
|
||||
for node in layers[i]:
|
||||
if node not in ls["olayer"]:
|
||||
ls["olayer"].append(node)
|
||||
for layer, layernodes in enumerate(layer_structure):
|
||||
for j, n in enumerate(layernodes["olayer"]):
|
||||
node_position[n] = j
|
||||
node_layer[n] = layer
|
||||
print(crossweight(node_position, node_layer, edges))
|
||||
node_position, node_layer, newls = ordernodes(layers, orders, edges)
|
||||
layer_structure = []
|
||||
density = []
|
||||
for i in range(5):
|
||||
ls = layer_structure[i]
|
||||
ls["num"] = len(ls["olayer"])
|
||||
ls = {}
|
||||
ls["olayer"] = newls[i]
|
||||
ls["num"] = len(newls[i])
|
||||
ls["inout"] = 0
|
||||
for j in ls["olayer"]:
|
||||
lhi = 0
|
||||
@ -1239,6 +1303,7 @@ def printsvg():
|
||||
print(json.dumps(layer_structure, indent=2))
|
||||
print(json.dumps(node_structure, indent=2))
|
||||
ls["inout"] += k["size"]
|
||||
layer_structure.append(ls)
|
||||
if height == 0:
|
||||
minheight = 0
|
||||
for i in range(5):
|
||||
|
Loading…
Reference in New Issue
Block a user