-- demo\rosetta\Functional_coverage_tree.exw with javascript_semantics constant data = """ NAME_HIERARCHY | WEIGHT | COVERAGE | cleaning | | | house1 |40 | | bedrooms | |0.25 | bathrooms | | | bathroom1 | |0.5 | bathroom2 | | | outside_lavatory | |1 | attic | |0.75 | kitchen | |0.1 | living_rooms | | | lounge | | | dining_room | | | conservatory | | | playroom | |1 | basement | | | garage | | | garden | |0.8 | house2 |60 | | upstairs | | | bedrooms | | | suite_1 | | | suite_2 | | | bedroom_3 | | | bedroom_4 | | | bathroom | | | toilet | | | attics | |0.6 | groundfloor | | | kitchen | | | living_rooms | | | lounge | | | dining_room | | | conservatory | | | playroom | | | wet_room_&_toilet | | | garage | | | garden | |0.9 | hot_tub_suite | |1 | basement | | | cellars | |1 | wine_cellar | |1 | cinema | |0.75 | """ sequence lines = split(data,"\n"), pi = {}, -- indents (to locate parents) pdx = {}, -- indexes for "" children string desc, weights, covers integer parent, child atom weight, coverage, childw = 0 enum DESC, WEIGHT, COVERAGE, PARENT, CHILDREN, CHILDW lines[DESC] &= " SHARE OF RESIDUE" for i=2 to length(lines) do -- decode text to useable data, link up parents & children {desc,weights,covers} = split(lines[i],"|") -- (nb this assumes /totally/ consistent indenting) integer indent = length(desc)-length(trim_head(desc)), k = find(indent,pi) if k=0 then pi = append(pi,indent) pdx = append(pdx,0) k = length(pi) end if pdx[k] = i parent = 0 if k>1 then parent = pdx[k-1] -- lines[parent][CHILDREN] &= i lines[parent][CHILDREN] = deep_copy(lines[parent][CHILDREN]) & i end if children = {} weight = to_number(trim(weights),1) coverage = to_number(trim(covers),0) lines[i] = {desc, weight, coverage, parent, children, childw} end for for i=length(lines) to 2 by -1 do -- calculate the parent coverages, and save child weight sums children = lines[i][CHILDREN] if length(children) then coverage = 0 childw = 0 for c=1 to length(children) do child = children[c] atom w = lines[child][WEIGHT] coverage += lines[child][COVERAGE]*w childw += w end for lines[i][COVERAGE] = coverage/childw lines[i][CHILDW] = childw -- (save for next loop) end if end for for i=length(lines) to 2 by -1 do -- calculate the share of residue, and format lines child = i {desc, weight, coverage, parent} = lines[i] atom residue = 1-coverage while parent do residue *= lines[child][WEIGHT]/lines[parent][CHILDW] {child, parent} = {parent, lines[parent][PARENT]} end while lines[i] = sprintf("%-32s| %6d | %-8g | %g",{desc,weight,coverage,residue}) end for puts(1,join(lines,"\n")&"\n") {} = wait_key()