forked from dubacq/scodoc-cohortes
Add mixed dataviz. CLI not operational yet.
This commit is contained in:
parent
b33370daaf
commit
3b7a3df51c
148
get.py
148
get.py
@ -97,7 +97,6 @@ def cli_check():
|
||||
global depts
|
||||
|
||||
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(
|
||||
"--base",
|
||||
@ -146,7 +145,6 @@ def cli_check():
|
||||
args.depts.insert(0, args.optimize)
|
||||
|
||||
Options.base_year = args.base
|
||||
Options.techno = args.techno
|
||||
depts = args.depts
|
||||
orderkey = "_".join(depts)
|
||||
|
||||
@ -181,32 +179,37 @@ def write_conf(key, obj):
|
||||
|
||||
conf = read_conf(orderkey)
|
||||
|
||||
defaults = {
|
||||
"spacing": 14,
|
||||
"thickness": 6,
|
||||
"fontsize_name": 10,
|
||||
"fontsize_count": 14,
|
||||
"width": 1300,
|
||||
"height": 0,
|
||||
"hmargin": 20,
|
||||
"parcours_separator": "/",
|
||||
"year_separator": " ",
|
||||
"rank_separator": "",
|
||||
"diplome_separator": "",
|
||||
"reuse": "yes",
|
||||
"optimize": "yes",
|
||||
"main_filter": 0,
|
||||
"secondary_filter": 1,
|
||||
}
|
||||
|
||||
|
||||
def conf_value(xkey: str):
|
||||
"""Manage default values"""
|
||||
defaults = {
|
||||
"spacing": 14,
|
||||
"thickness": 6,
|
||||
"fontsize_name": 10,
|
||||
"fontsize_count": 14,
|
||||
"width": 1300,
|
||||
"height": 0,
|
||||
"hmargin": 20,
|
||||
"parcours_separator": "/",
|
||||
"year_separator": " ",
|
||||
"rank_separator": "",
|
||||
"diplome_separator": "",
|
||||
"reuse": "yes",
|
||||
"optimize": "yes",
|
||||
}
|
||||
if xkey in conf:
|
||||
return conf[xkey]
|
||||
if xkey in defaults:
|
||||
return defaults[xkey]
|
||||
if xkey[-9:] == "separator":
|
||||
return " "
|
||||
if xkey == "nick" or xkey == "displayname":
|
||||
if xkey == "nick":
|
||||
return "{diplome}{rank}{multidepartment}{modalite}{parcours}{year}"
|
||||
if xkey == "displayname":
|
||||
return "{diplome}{rank}{multidepartment}{modaliteshort}{parcours}"
|
||||
if xkey == "extnick":
|
||||
return "{ext}{rank}{multidepartment}{diplomenobut}{modaliteshort}"
|
||||
if xkey == "orders":
|
||||
@ -588,12 +591,6 @@ def analyse_depts():
|
||||
else:
|
||||
studentsummary["civilite"] = "?"
|
||||
bacs.add(studentsummary["bac"])
|
||||
# We skip non-techno students if we are in techno mode
|
||||
# If we want a mixed reporting, maybe we should change this
|
||||
if (
|
||||
Options.techno and studentsummary["bac"][:2] != "ST"
|
||||
): # TODO: change this
|
||||
continue
|
||||
if bucket in studentsummary["cursus"]:
|
||||
semestreerreur = int(bucket) + 1
|
||||
warning(
|
||||
@ -1007,7 +1004,9 @@ for etudid in student.keys():
|
||||
goodred[ddd] += 1
|
||||
output = finaloutput + " " + etud["nickshort"][lastyear]
|
||||
etud["nickshort"][lastyear + 1] = output
|
||||
displaynames[output] = finals[finaloutput] + etud["nickshort"][lastyear]
|
||||
displaynames[output] = (
|
||||
finals[finaloutput] + displaynames[etud["nickshort"][lastyear]]
|
||||
)
|
||||
(firstsem, firstyear) = (
|
||||
(etud["short"][1], 1)
|
||||
if etud["short"][1] != None
|
||||
@ -1054,8 +1053,15 @@ for etudid in student.keys():
|
||||
|
||||
|
||||
class Filter:
|
||||
# Filter on students to be considered
|
||||
# 1 consider only technological baccalaureates, statistics are always asked
|
||||
# 2 consider only women, because gender statistics are frequently asked
|
||||
# 4 consider only incoming students (primo-entrants) in first year of the cohort
|
||||
# 8 consider only people having a first year, not parallel entries
|
||||
TECHNO = 1
|
||||
WOMAN = 2
|
||||
PRIMO = 4
|
||||
MAIN = 8
|
||||
|
||||
|
||||
def bags_from_students(student, filter=0):
|
||||
@ -1253,32 +1259,31 @@ def get_layer_structure(newls, node_structure, spacing, hmargin, height):
|
||||
for j in ls["olayer"]:
|
||||
lhi = 0
|
||||
lho = 0
|
||||
slhi = 0
|
||||
slho = 0
|
||||
k = node_structure[j]
|
||||
for prev_node in k["prev"]:
|
||||
lhi += prev_node[1]
|
||||
slhi += prev_node[2]
|
||||
for next_node in k["next"]:
|
||||
lho += next_node[1]
|
||||
slho += next_node[2]
|
||||
k["size"] = max(lhi, lho)
|
||||
k["ssize"] = max(slhi, slho)
|
||||
k["in"] = lhi
|
||||
k["out"] = lho
|
||||
if lhi != lho and lhi * lho != 0:
|
||||
print(f"BUG1: {j} {k} {lhi} {lho}")
|
||||
print(json.dumps(layer_structure, indent=2))
|
||||
print(json.dumps(node_structure, indent=2))
|
||||
warning(f"BUG1: {j} {k} {lhi} {lho}")
|
||||
ls["inout"] += k["size"]
|
||||
layer_structure.append(ls)
|
||||
if height == 0:
|
||||
debug("coucou")
|
||||
minheight = 0
|
||||
for i in range(5):
|
||||
ls = layer_structure[i]
|
||||
new_minheight = spacing * (ls["num"] - 1) + 2 * hmargin + 2 * ls["inout"]
|
||||
debug(f"{new_minheight} / {minheight}")
|
||||
if new_minheight > minheight:
|
||||
minheight = new_minheight
|
||||
height = (1 + (minheight // 150)) * 150
|
||||
debug(f"{height}")
|
||||
|
||||
for i in range(5):
|
||||
ls = layer_structure[i]
|
||||
ls["density"] = ls["inout"] / (
|
||||
@ -1300,6 +1305,8 @@ def get_layer_structure(newls, node_structure, spacing, hmargin, height):
|
||||
ns = node_structure[j]
|
||||
ns["top"] = supp_spacing + spacing + cs
|
||||
h = ns["size"] / realdensity
|
||||
sh = ns["ssize"] / realdensity
|
||||
ns["middle"] = ns["top"] + sh
|
||||
cs = ns["bottom"] = ns["top"] + h
|
||||
return realdensity, height, layer_structure
|
||||
|
||||
@ -1308,6 +1315,14 @@ def nodestructure_from_bags(bags, sbags=None):
|
||||
node_structure = {}
|
||||
layers = [[], [], [], [], []]
|
||||
edges = []
|
||||
union_sbag = {}
|
||||
if sbags is not None:
|
||||
for layer, layernodes in enumerate(sbags):
|
||||
for startnode in layernodes:
|
||||
for endnode in layernodes[startnode]:
|
||||
if startnode not in union_sbag:
|
||||
union_sbag[startnode] = {}
|
||||
union_sbag[startnode][endnode] = layernodes[startnode][endnode]
|
||||
for layer, layernodes in enumerate(bags):
|
||||
for startnode in layernodes:
|
||||
# if startnode[-1] == "*":
|
||||
@ -1316,24 +1331,30 @@ def nodestructure_from_bags(bags, sbags=None):
|
||||
# if endnode[-1] == "*":
|
||||
# continue
|
||||
weight = layernodes[startnode][endnode]
|
||||
if startnode in union_sbag and endnode in union_sbag[startnode]:
|
||||
sweight = union_sbag[startnode][endnode]
|
||||
elif sbags is None:
|
||||
sweight = -1
|
||||
else:
|
||||
sweight = 0
|
||||
if endnode not in node_structure:
|
||||
node_structure[endnode] = {
|
||||
"prev": [[startnode, weight]],
|
||||
"prev": [[startnode, weight, sweight]],
|
||||
"next": [],
|
||||
"layer": layer + 1,
|
||||
}
|
||||
layers[layer + 1].append(endnode)
|
||||
else:
|
||||
node_structure[endnode]["prev"].append([startnode, weight])
|
||||
node_structure[endnode]["prev"].append([startnode, weight, sweight])
|
||||
if startnode not in node_structure:
|
||||
node_structure[startnode] = {
|
||||
"prev": [],
|
||||
"next": [[endnode, weight]],
|
||||
"next": [[endnode, weight, sweight]],
|
||||
"layer": layer,
|
||||
}
|
||||
layers[layer].append(startnode)
|
||||
else:
|
||||
node_structure[startnode]["next"].append([endnode, weight])
|
||||
node_structure[startnode]["next"].append([endnode, weight, sweight])
|
||||
edges.append([startnode, endnode, weight])
|
||||
return node_structure, layers, edges
|
||||
|
||||
@ -1366,6 +1387,17 @@ def compute_svg(height, padding, realdensity, node_structure):
|
||||
2 * thickness,
|
||||
ns["bottom"] - ns["top"],
|
||||
fill=col,
|
||||
opacity=0.5,
|
||||
stroke_width=0.1,
|
||||
stroke="#808080",
|
||||
)
|
||||
g1.append(r)
|
||||
r = drawsvg.Rectangle(
|
||||
xpos - thickness,
|
||||
ns["top"],
|
||||
2 * thickness,
|
||||
ns["middle"] - ns["top"],
|
||||
fill=col,
|
||||
stroke_width=0.2,
|
||||
stroke="black",
|
||||
)
|
||||
@ -1426,16 +1458,20 @@ def compute_svg(height, padding, realdensity, node_structure):
|
||||
ns["next"].sort(key=lambda x: node_structure[x[0]]["top"])
|
||||
start = ns["top"]
|
||||
for link in ns["prev"]:
|
||||
ysize = link[-1]
|
||||
ysize = link[1]
|
||||
sysize = link[2]
|
||||
link.append(start)
|
||||
link.append(start + sysize / realdensity)
|
||||
start += ysize / realdensity
|
||||
link.append(start)
|
||||
for n in node_structure:
|
||||
ns = node_structure[n]
|
||||
start = ns["top"]
|
||||
for link in ns["next"]:
|
||||
ysize = link[-1]
|
||||
ysize = link[1]
|
||||
sysize = link[2]
|
||||
link.append(start)
|
||||
link.append(start + sysize / realdensity)
|
||||
start += ysize / realdensity
|
||||
link.append(start)
|
||||
targets = node_structure[link[0]]
|
||||
@ -1446,7 +1482,7 @@ def compute_svg(height, padding, realdensity, node_structure):
|
||||
if target == None:
|
||||
print(f"BUG: {n},{ns},{t}")
|
||||
sys.exit(5)
|
||||
|
||||
# At this point, link has values target_name, size, secondary_size, top, middle, bottom
|
||||
posxa = columns[ns["layer"]] + thickness
|
||||
posxb = columns[targets["layer"]] - thickness
|
||||
posxc = (3 * posxa + posxb) / 4
|
||||
@ -1454,12 +1490,31 @@ def compute_svg(height, padding, realdensity, node_structure):
|
||||
grad = drawsvg.LinearGradient(posxa, 0, posxb, 0)
|
||||
grad.add_stop(0, ns["color"], opacity=0.5)
|
||||
grad.add_stop(1, targets["color"], opacity=0.5)
|
||||
p = drawsvg.Path(fill=grad, stroke_width=0)
|
||||
p.M(posxa, link[-2])
|
||||
p.C(posxc, link[-2], posxd, target[-2], posxb, target[-2])
|
||||
p.L(posxb, target[-1])
|
||||
p.C(posxd, target[-1], posxc, link[-1], posxa, link[-1])
|
||||
posyat = link[3]
|
||||
posyam = link[4]
|
||||
posyab = link[5]
|
||||
posybt = target[3]
|
||||
posybm = target[4]
|
||||
posybb = target[5]
|
||||
p = drawsvg.Path(fill=grad, stroke="#000", stroke_width=0, opacity=0.8)
|
||||
p.M(posxa, posyab)
|
||||
p.C(posxc, posyab, posxd, posybb, posxb, posybb)
|
||||
p.L(posxb, posybt)
|
||||
p.C(posxd, posybt, posxc, posyat, posxa, posyat)
|
||||
p.Z()
|
||||
p.append_title(
|
||||
f"{displaynames[n]}=>{displaynames[link[0]]}: {link[2]}/{link[1]}"
|
||||
)
|
||||
g2.append(p)
|
||||
p = drawsvg.Path(fill=grad, stroke="#000", stroke_width=0)
|
||||
p.M(posxa, posyam)
|
||||
p.C(posxc, posyam, posxd, posybm, posxb, posybm)
|
||||
p.L(posxb, posybt)
|
||||
p.C(posxd, posybt, posxc, posyat, posxa, posyat)
|
||||
p.Z()
|
||||
p.append_title(
|
||||
f"{displaynames[n]}=>{displaynames[link[0]]}: {link[2]}/{link[1]}"
|
||||
)
|
||||
g2.append(p)
|
||||
d.append(g2)
|
||||
d.append(g1)
|
||||
@ -1473,8 +1528,9 @@ def printsvg():
|
||||
spacing = conf_value("spacing")
|
||||
height = conf_value("height")
|
||||
hmargin = conf_value("hmargin")
|
||||
bags = bags_from_students(student, 0)
|
||||
node_structure, layers, edges = nodestructure_from_bags(bags)
|
||||
bags = bags_from_students(student, conf_value("main_filter"))
|
||||
sbags = bags_from_students(student, conf_value("secondary_filter"))
|
||||
node_structure, layers, edges = nodestructure_from_bags(bags, sbags)
|
||||
filename = "best-" + orderkey
|
||||
if Options.restart:
|
||||
try:
|
||||
|
Loading…
Reference in New Issue
Block a user