Remove bundle_combine logic from lib + small changes
This commit is contained in:
@@ -49,7 +49,7 @@ digraph Dependency {
|
||||
index_meta -> html_index_domains
|
||||
"." -> bundle_combine
|
||||
bundle_combine -> index_meta
|
||||
bundle_combine -> html_bundle
|
||||
index_meta -> html_bundle
|
||||
bundle_combine -> index_domains
|
||||
index_domains -> html_index_domains
|
||||
"." -> tracker_download
|
||||
|
||||
@@ -4,33 +4,25 @@ import os
|
||||
import re
|
||||
import sys
|
||||
import common_lib as mylib
|
||||
import tracker_download
|
||||
import tracker_download # is_tracker
|
||||
|
||||
|
||||
THRESHOLD_PERCENT_OF_LOGS = 0.33 # domain appears in % recordings
|
||||
THRESHOLD_MIN_AVG_LOGS = 0.4 # at least x times in total (after %-thresh)
|
||||
|
||||
level3_doms = None
|
||||
re_domain = re.compile(r'[^a-zA-Z0-9.-]')
|
||||
|
||||
|
||||
def dom_in_3rd_domain(needle):
|
||||
global level3_doms
|
||||
if not level3_doms:
|
||||
level3_doms = mylib.read_list('3rd-domains.txt')
|
||||
return mylib.bintree_lookup(level3_doms, needle)
|
||||
def fname_combined(bundle_id):
|
||||
return mylib.path_data_app(bundle_id, 'combined.json')
|
||||
|
||||
|
||||
def get_parent_domain(subdomain):
|
||||
parts = subdomain.split('.')
|
||||
if len(parts) < 3:
|
||||
return subdomain
|
||||
elif parts[-1].isdigit():
|
||||
return subdomain # ip address
|
||||
elif dom_in_3rd_domain(parts[-1] + '.' + parts[-2]):
|
||||
return '.'.join(parts[-3:])
|
||||
else:
|
||||
return '.'.join(parts[-2:])
|
||||
def fname_evaluated(bundle_id):
|
||||
return mylib.path_data_app(bundle_id, 'evaluated.json')
|
||||
|
||||
|
||||
def get_evaluated(bundle_id):
|
||||
return mylib.json_read(fname_evaluated(bundle_id))
|
||||
|
||||
|
||||
def cleanup_domain_name(domain):
|
||||
@@ -66,7 +58,7 @@ def json_combine(bundle_id):
|
||||
occurs = len(logs[subdomain])
|
||||
subdomain = cleanup_domain_name(subdomain)
|
||||
inc_dic(subdom, subdomain, occurs)
|
||||
par_dom = get_parent_domain(subdomain)
|
||||
par_dom = mylib.parent_domain(subdomain)
|
||||
try:
|
||||
uniq_par[par_dom] += occurs
|
||||
except KeyError:
|
||||
@@ -81,6 +73,24 @@ def json_combine(bundle_id):
|
||||
return res
|
||||
|
||||
|
||||
def evaluate_domains(ddic, number_of_recordings):
|
||||
res = []
|
||||
c_sum = 0
|
||||
c_trkr = 0
|
||||
for name, (is_tracker, counts) in ddic.items():
|
||||
rec_percent = len(counts) / number_of_recordings
|
||||
if rec_percent < THRESHOLD_PERCENT_OF_LOGS:
|
||||
continue
|
||||
avg = sum(counts) / number_of_recordings # len(counts)
|
||||
if avg < THRESHOLD_MIN_AVG_LOGS:
|
||||
continue
|
||||
res.append([name, round(avg + 0.001), is_tracker])
|
||||
c_sum += avg
|
||||
c_trkr += avg if is_tracker else 0
|
||||
res.sort(key=lambda x: (-x[1], x[0])) # sort by count desc, then name
|
||||
return res, c_trkr, c_sum
|
||||
|
||||
|
||||
def json_evaluate_inplace(obj):
|
||||
def float3(val):
|
||||
return int(val * 1000) / 1000
|
||||
@@ -93,26 +103,8 @@ def json_evaluate_inplace(obj):
|
||||
obj['sum_logs_pm'] = float3(obj['sum_logs'] / (time_total or 1) * 60)
|
||||
obj['sum_time'] = time_total
|
||||
obj['avg_time'] = float3(time_total / rec_count)
|
||||
|
||||
def transform(ddic):
|
||||
res = []
|
||||
c_sum = 0
|
||||
c_trkr = 0
|
||||
for name, (is_tracker, counts) in ddic.items():
|
||||
rec_percent = len(counts) / rec_count
|
||||
if rec_percent < THRESHOLD_PERCENT_OF_LOGS:
|
||||
continue
|
||||
avg = sum(counts) / rec_count # len(counts)
|
||||
if avg < THRESHOLD_MIN_AVG_LOGS:
|
||||
continue
|
||||
res.append([name, round(avg + 0.001), is_tracker])
|
||||
c_sum += avg
|
||||
c_trkr += avg if is_tracker else 0
|
||||
res.sort(key=lambda x: (-x[1], x[0])) # sort by count desc, then name
|
||||
return res, c_trkr, c_sum
|
||||
|
||||
obj['pardom'], p_t, p_c = transform(obj['pardom'])
|
||||
obj['subdom'], s_t, s_c = transform(obj['subdom'])
|
||||
obj['pardom'], p_t, p_c = evaluate_domains(obj['pardom'], rec_count)
|
||||
obj['subdom'], s_t, s_c = evaluate_domains(obj['subdom'], rec_count)
|
||||
obj['tracker_percent'] = float3(s_t / (s_c or 1))
|
||||
obj['avg_logs'] = float3(s_c)
|
||||
obj['avg_logs_pm'] = float3(s_c / (obj['avg_time'] or 1) * 60)
|
||||
@@ -137,9 +129,9 @@ def process(bundle_ids, where=None):
|
||||
break
|
||||
if should_update:
|
||||
print(' ' + bid)
|
||||
mylib.json_write_combined(bid, obj)
|
||||
mylib.json_write(fname_combined(bid), obj, pretty=False)
|
||||
json_evaluate_inplace(obj)
|
||||
mylib.json_write_evaluated(bid, obj)
|
||||
mylib.json_write(fname_evaluated(bid), obj, pretty=False)
|
||||
affected_ids.append(bid)
|
||||
print('')
|
||||
return affected_ids
|
||||
|
||||
@@ -94,6 +94,9 @@ def printf(msg):
|
||||
|
||||
# Binary Tree Search
|
||||
|
||||
_list_TLD = None
|
||||
|
||||
|
||||
def read_list(list_name):
|
||||
path = path_root('src', 'lists', list_name)
|
||||
if not file_exists(path):
|
||||
@@ -118,6 +121,24 @@ def bintree_lookup(tree, needle):
|
||||
return False # -1
|
||||
|
||||
|
||||
def parent_domain(subdomain):
|
||||
def is_third_level(needle):
|
||||
global _list_TLD
|
||||
if not _list_TLD:
|
||||
_list_TLD = read_list('3rd-domains.txt')
|
||||
return bintree_lookup(_list_TLD, needle)
|
||||
|
||||
parts = subdomain.split('.')
|
||||
if len(parts) < 3:
|
||||
return subdomain
|
||||
elif parts[-1].isdigit():
|
||||
return subdomain # ip address
|
||||
elif is_third_level(parts[-1] + '.' + parts[-2]):
|
||||
return '.'.join(parts[-3:])
|
||||
else:
|
||||
return '.'.join(parts[-2:])
|
||||
|
||||
|
||||
# Filesystem
|
||||
|
||||
def mkdir(path):
|
||||
@@ -252,27 +273,6 @@ def json_read(path):
|
||||
return json.load(fp)
|
||||
|
||||
|
||||
def json_read_combined(bundle_id):
|
||||
return json_read(path_data_app(bundle_id, 'combined.json'))
|
||||
|
||||
|
||||
def json_read_evaluated(bundle_id):
|
||||
pth = path_data_app(bundle_id, 'evaluated.json')
|
||||
return json_read(pth), pth
|
||||
|
||||
|
||||
# JSON write
|
||||
|
||||
def json_write(path, obj, pretty=False):
|
||||
with open(path, 'w') as fp:
|
||||
json.dump(obj, fp, indent=2 if pretty else None, sort_keys=pretty)
|
||||
|
||||
|
||||
def json_write_combined(bundle_id, obj):
|
||||
fname = path_data_app(bundle_id, 'combined.json')
|
||||
json_write(fname, obj, pretty=False)
|
||||
|
||||
|
||||
def json_write_evaluated(bundle_id, obj):
|
||||
fname = path_data_app(bundle_id, 'evaluated.json')
|
||||
json_write(fname, obj, pretty=False)
|
||||
|
||||
@@ -4,9 +4,10 @@ import sys
|
||||
import time
|
||||
import math
|
||||
import common_lib as mylib
|
||||
import bundle_download
|
||||
import index_app_names
|
||||
import index_meta
|
||||
import bundle_download # get_genres
|
||||
import bundle_combine # get_evaluated, fname_evaluated
|
||||
import index_app_names # get_name
|
||||
import index_meta # get_rank
|
||||
|
||||
|
||||
def gen_dotgraph(sorted_arr):
|
||||
@@ -155,17 +156,18 @@ def gen_html(bundle_id, obj):
|
||||
|
||||
|
||||
def process(bundle_ids):
|
||||
print('generating html pages ...')
|
||||
print('generating html: apps ...')
|
||||
if bundle_ids == ['*']:
|
||||
bundle_ids = list(mylib.enum_appids())
|
||||
|
||||
for bid in bundle_ids:
|
||||
print(' ' + bid)
|
||||
json, json_data_path = mylib.json_read_evaluated(bid)
|
||||
json = bundle_combine.get_evaluated(bid)
|
||||
mylib.mkdir_out_app(bid)
|
||||
with open(mylib.path_out_app(bid, 'index.html'), 'w') as fp:
|
||||
fp.write(gen_html(bid, json))
|
||||
mylib.symlink(json_data_path, mylib.path_out_app(bid, 'data.json'))
|
||||
mylib.symlink(bundle_combine.fname_evaluated(bid),
|
||||
mylib.path_out_app(bid, 'data.json'))
|
||||
print('')
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import common_lib as mylib
|
||||
import index_app_names
|
||||
import index_app_names # get_name
|
||||
|
||||
|
||||
def gen_obj(bundle_id):
|
||||
@@ -60,7 +60,7 @@ def gen_page(arr, base, page_id=1, total=1):
|
||||
|
||||
|
||||
def process(per_page=60):
|
||||
print('generating app-index ...')
|
||||
print('generating html: app-index ...')
|
||||
index_dir = mylib.path_out('index', 'apps')
|
||||
mylib.rm_dir(index_dir)
|
||||
mylib.mkdir(index_dir)
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import common_lib as mylib
|
||||
import index_app_names
|
||||
import index_app_names # get_name
|
||||
import index_domains
|
||||
import index_meta
|
||||
import index_meta # get_total_counts
|
||||
|
||||
|
||||
def a_app(bundle_id):
|
||||
@@ -117,6 +117,10 @@ def gen_html_lookup(html_dir, json, key, title):
|
||||
|
||||
def gen_html_stats(c_apps, c_domains):
|
||||
[c_recordings, c_logs] = index_meta.get_total_counts()
|
||||
print(' {} apps'.format(c_apps))
|
||||
print(' {} domains'.format(c_domains))
|
||||
print(' {} recordings'.format(c_recordings))
|
||||
print(' {} logs'.format(c_logs))
|
||||
title = 'Statistics'
|
||||
mylib.mkdir(mylib.path_out('stats'))
|
||||
with open(mylib.path_out('stats', 'index.html'), 'w') as fp:
|
||||
@@ -137,7 +141,7 @@ def gen_html_stats(c_apps, c_domains):
|
||||
|
||||
def process():
|
||||
# bundle_combine assures domain name is [a-zA-Z0-9.-]
|
||||
print('generating domain-index ...')
|
||||
print('generating html: domain-index ...')
|
||||
# Data export
|
||||
all_dom_dir = mylib.path_out('index', 'domains', 'all')
|
||||
trkr_dir = mylib.path_out('index', 'domains', 'tracker')
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
import sys
|
||||
import common_lib as mylib
|
||||
import bundle_download # app_names
|
||||
|
||||
_bundle_name_dict = None
|
||||
|
||||
@@ -25,7 +26,7 @@ def load_json_if_not_already():
|
||||
|
||||
|
||||
def write_json_to_disk():
|
||||
mylib.json_write(index_fname(), _bundle_name_dict, pretty=True)
|
||||
mylib.json_write(index_fname(), _bundle_name_dict, pretty=False)
|
||||
|
||||
|
||||
def get_name(bundle_id, langs=['us', 'de'], fallback='< App-Name >'):
|
||||
@@ -39,7 +40,7 @@ def get_name(bundle_id, langs=['us', 'de'], fallback='< App-Name >'):
|
||||
|
||||
|
||||
def process(bundle_ids):
|
||||
print('writing index: bundle name ...')
|
||||
print('writing index: app names ...')
|
||||
if bundle_ids == ['*']:
|
||||
bundle_ids = list(mylib.enum_data_appids())
|
||||
print(' full reset')
|
||||
@@ -48,7 +49,7 @@ def process(bundle_ids):
|
||||
load_json_if_not_already()
|
||||
did_change = False
|
||||
for bid in bundle_ids:
|
||||
names = mylib.app_names(bid)
|
||||
names = bundle_download.app_names(bid)
|
||||
if not names:
|
||||
mylib.err('index-app-names', 'could not load: {}'.format(bid))
|
||||
continue
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
import sys
|
||||
import common_lib as mylib
|
||||
import bundle_combine
|
||||
import tracker_download
|
||||
import bundle_combine # get_evaluated
|
||||
import tracker_download # is_tracker
|
||||
|
||||
|
||||
def fname_all():
|
||||
@@ -55,7 +55,7 @@ def insert_in_index(index, bundle_ids):
|
||||
except ValueError: # index not found
|
||||
i = len(index['bundle'])
|
||||
index['bundle'].append(bid)
|
||||
json, _ = mylib.json_read_evaluated(bid)
|
||||
json = bundle_combine.get_evaluated(bid)
|
||||
for key in ['pardom', 'subdom']: # assuming keys are identical
|
||||
for domain, _, _ in json[key]:
|
||||
try:
|
||||
@@ -72,7 +72,7 @@ def filter_tracker_only(index):
|
||||
for domain, ids in filter(lambda x: tracker_download.is_tracker(x[0]),
|
||||
index['subdom'].items()):
|
||||
sub_trkr[domain] = ids
|
||||
pardom = bundle_combine.get_parent_domain(domain)
|
||||
pardom = mylib.parent_domain(domain)
|
||||
try:
|
||||
par_trkr[pardom].update(ids)
|
||||
except KeyError:
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
import sys
|
||||
import common_lib as mylib
|
||||
import bundle_combine # get_evaluated
|
||||
|
||||
_rank_dict = None
|
||||
|
||||
@@ -65,8 +66,7 @@ def write_summary_index(index, bundle_ids, deleteOnly=False):
|
||||
if deleteOnly:
|
||||
continue
|
||||
# set new value
|
||||
evaluated_json, _ = mylib.json_read_evaluated(bid)
|
||||
index[bid] = json_to_list(evaluated_json)
|
||||
index[bid] = json_to_list(bundle_combine.get_evaluated(bid))
|
||||
|
||||
# sum of counts
|
||||
try_del(index, ['_sum'])
|
||||
@@ -82,26 +82,27 @@ def write_rank_index(index):
|
||||
try_del(index, ['_sum', '_ranks', '_min', '_max'])
|
||||
mins = []
|
||||
maxs = []
|
||||
for i in range(11): # equal to number of array entries
|
||||
tmp = {}
|
||||
# make temporary reverse index
|
||||
for bid, val in index.items():
|
||||
try:
|
||||
tmp[val[i]].append(bid)
|
||||
except KeyError:
|
||||
tmp[val[i]] = [bid]
|
||||
# read index position from temp reverse index
|
||||
r = 1
|
||||
ordered = sorted(tmp.items(), reverse=i in [0, 3, 6, 7])
|
||||
for idx, (_, ids) in enumerate(ordered):
|
||||
for bid in ids:
|
||||
index[bid][i] = r
|
||||
r += len(ids)
|
||||
mins.append(ordered[0][0])
|
||||
maxs.append(ordered[-1][0])
|
||||
if len(index) > 0:
|
||||
for i in range(11): # equal to number of array entries
|
||||
tmp = {}
|
||||
# make temporary reverse index
|
||||
for bid, val in index.items():
|
||||
try:
|
||||
tmp[val[i]].append(bid)
|
||||
except KeyError:
|
||||
tmp[val[i]] = [bid]
|
||||
# read index position from temp reverse index
|
||||
r = 1
|
||||
ordered = sorted(tmp.items(), reverse=i in [0, 3, 6, 7])
|
||||
for idx, (_, ids) in enumerate(ordered):
|
||||
for bid in ids:
|
||||
index[bid][i] = r
|
||||
r += len(ids)
|
||||
mins.append(ordered[0][0])
|
||||
maxs.append(ordered[-1][0])
|
||||
index['_ranks'] = len(index)
|
||||
index['_min'] = mins
|
||||
index['_max'] = maxs
|
||||
index['_ranks'] = len(index)
|
||||
mylib.json_write(fname_app_rank(), index, pretty=False)
|
||||
|
||||
|
||||
|
||||
28
src/main.py
28
src/main.py
@@ -35,18 +35,10 @@ def rebuild_app_index_html(inclRoot=False):
|
||||
|
||||
|
||||
def rebuild_domain_index(bundle_ids, deleteOnly=False):
|
||||
index_meta.process(bundle_ids, deleteOnly=deleteOnly)
|
||||
index_domains.process(bundle_ids, deleteOnly=deleteOnly)
|
||||
html_index_domains.process()
|
||||
|
||||
|
||||
def rebuild_name_index(new_ids):
|
||||
if index_app_names.missing():
|
||||
index_app_names.process(['*'])
|
||||
elif len(new_ids) > 0:
|
||||
index_app_names.process(new_ids) # after bundle_download
|
||||
|
||||
|
||||
def del_id(bundle_ids):
|
||||
print('removing apps from website:')
|
||||
if bundle_ids == ['*']:
|
||||
@@ -60,30 +52,35 @@ def del_id(bundle_ids):
|
||||
mylib.rm_dir(dest)
|
||||
update_app_index = True
|
||||
print('')
|
||||
index_meta.process(bundle_ids, deleteOnly=True)
|
||||
rebuild_domain_index(bundle_ids, deleteOnly=True)
|
||||
if update_app_index:
|
||||
rebuild_app_index_html(inclRoot=True)
|
||||
|
||||
|
||||
def combine_and_update(bundle_ids, where=None):
|
||||
def star_reset(ids):
|
||||
# special case needed. '*' will force rebuilt index
|
||||
return ['*'] if not where and bundle_ids == ['*'] else ids
|
||||
# 1. download meta data from iTunes store, incl. app icons
|
||||
new_ids = bundle_download.process(bundle_ids)
|
||||
new_ids = star_reset(new_ids)
|
||||
# 2. if new apps, update bundle name index
|
||||
rebuild_name_index(new_ids) # after bundle_download
|
||||
if len(new_ids) > 0:
|
||||
index_app_names.process(new_ids) # after bundle_download
|
||||
# 3. re-calculate combined.json and evaluated.json files
|
||||
affected = bundle_combine.process(bundle_ids, where=where)
|
||||
# special case needed for domain index. '*' will force rebuilt index
|
||||
if not where and bundle_ids == ['*']:
|
||||
affected = ['*']
|
||||
affected = star_reset(affected)
|
||||
# 4. was any json updated? if so, make html and update domain index
|
||||
if len(affected) > 0:
|
||||
rebuild_domain_index(affected) # after bundle_combine
|
||||
index_meta.process(bundle_ids) # after bundle_combine
|
||||
html_bundle.process(affected) # after index_app_names
|
||||
rebuild_domain_index(affected) # after bundle_combine
|
||||
else:
|
||||
print('no bundle affected by tracker, not generating bundle html')
|
||||
# 5. make all apps index
|
||||
if len(new_ids) > 0:
|
||||
rebuild_app_index_html() # must be called after bundle_combine
|
||||
rebuild_app_index_html() # after bundle_combine
|
||||
else:
|
||||
print('no new bundle, not rebuilding index')
|
||||
|
||||
@@ -135,6 +132,7 @@ try:
|
||||
if bundle_download.download_missing_icons(force=False):
|
||||
rebuild_app_index_html()
|
||||
elif cmd == 'index':
|
||||
index_meta.process(['*'])
|
||||
rebuild_domain_index(['*'])
|
||||
rebuild_app_index_html(inclRoot=True)
|
||||
elif cmd == 'run':
|
||||
@@ -145,6 +143,8 @@ try:
|
||||
if len(params) == 0:
|
||||
print_usage_and_exit()
|
||||
del_id(params) # ['_manually']
|
||||
else:
|
||||
print_usage_and_exit()
|
||||
except Exception:
|
||||
mylib.err('critical', traceback.format_exc(), logOnly=True)
|
||||
raise
|
||||
|
||||
@@ -1,126 +1,126 @@
|
||||
<svg width="657pt" height="260pt" viewBox="0.00 0.00 657.00 260.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<svg width="632pt" height="260pt" viewBox="0.00 0.00 632.00 260.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="graph1" class="graph" transform="scale(1 1) rotate(0) translate(4 256)">
|
||||
<title>Dependency</title>
|
||||
<polygon fill="white" stroke="white" points="-4,5 -4,-256 654,-256 654,5 -4,5"></polygon>
|
||||
<polygon fill="white" stroke="white" points="-4,5 -4,-256 629,-256 629,5 -4,5"></polygon>
|
||||
<!-- . -->
|
||||
<g id="node1" class="node"><title>.</title>
|
||||
<ellipse fill="none" stroke="black" cx="303" cy="-234" rx="27" ry="18"></ellipse>
|
||||
<text text-anchor="middle" x="303" y="-229.8" font-family="Times,serif" font-size="14.00">.</text>
|
||||
<ellipse fill="none" stroke="black" cx="283" cy="-234" rx="27" ry="18"></ellipse>
|
||||
<text text-anchor="middle" x="283" y="-229.8" font-family="Times,serif" font-size="14.00">.</text>
|
||||
</g>
|
||||
<!-- html_root -->
|
||||
<g id="node3" class="node"><title>html_root</title>
|
||||
<ellipse fill="none" stroke="black" cx="73" cy="-162" rx="49.1927" ry="18"></ellipse>
|
||||
<text text-anchor="middle" x="73" y="-157.8" font-family="Times,serif" font-size="14.00">html_root</text>
|
||||
<ellipse fill="none" stroke="black" cx="49" cy="-162" rx="49.1927" ry="18"></ellipse>
|
||||
<text text-anchor="middle" x="49" y="-157.8" font-family="Times,serif" font-size="14.00">html_root</text>
|
||||
</g>
|
||||
<!-- .->html_root -->
|
||||
<g id="edge2" class="edge"><title>.->html_root</title>
|
||||
<path fill="none" stroke="black" d="M278.821,-225.641C241.055,-214.147 167.413,-191.734 119.229,-177.07"></path>
|
||||
<polygon fill="black" stroke="black" points="120.239,-173.719 109.653,-174.155 118.2,-180.415 120.239,-173.719"></polygon>
|
||||
<path fill="none" stroke="black" d="M258.839,-225.772C220.494,-214.302 145.019,-191.724 95.8145,-177.004"></path>
|
||||
<polygon fill="black" stroke="black" points="96.6233,-173.593 86.0396,-174.08 94.617,-180.299 96.6233,-173.593"></polygon>
|
||||
</g>
|
||||
<!-- bundle_download -->
|
||||
<g id="node5" class="node"><title>bundle_download</title>
|
||||
<ellipse fill="none" stroke="black" cx="390" cy="-162" rx="80.3504" ry="18"></ellipse>
|
||||
<text text-anchor="middle" x="390" y="-157.8" font-family="Times,serif" font-size="14.00">bundle_download</text>
|
||||
<ellipse fill="none" stroke="black" cx="196" cy="-162" rx="80.3504" ry="18"></ellipse>
|
||||
<text text-anchor="middle" x="196" y="-157.8" font-family="Times,serif" font-size="14.00">bundle_download</text>
|
||||
</g>
|
||||
<!-- .->bundle_download -->
|
||||
<g id="edge4" class="edge"><title>.->bundle_download</title>
|
||||
<path fill="none" stroke="black" d="M319.774,-219.503C331.662,-209.939 347.897,-196.876 361.763,-185.719"></path>
|
||||
<polygon fill="black" stroke="black" points="364.005,-188.408 369.602,-179.412 359.617,-182.954 364.005,-188.408"></polygon>
|
||||
<path fill="none" stroke="black" d="M266.226,-219.503C254.338,-209.939 238.103,-196.876 224.237,-185.719"></path>
|
||||
<polygon fill="black" stroke="black" points="226.383,-182.954 216.398,-179.412 221.995,-188.408 226.383,-182.954"></polygon>
|
||||
</g>
|
||||
<!-- bundle_combine -->
|
||||
<g id="node17" class="node"><title>bundle_combine</title>
|
||||
<ellipse fill="none" stroke="black" cx="216" cy="-162" rx="75.1062" ry="18"></ellipse>
|
||||
<text text-anchor="middle" x="216" y="-157.8" font-family="Times,serif" font-size="14.00">bundle_combine</text>
|
||||
<ellipse fill="none" stroke="black" cx="370" cy="-162" rx="75.1062" ry="18"></ellipse>
|
||||
<text text-anchor="middle" x="370" y="-157.8" font-family="Times,serif" font-size="14.00">bundle_combine</text>
|
||||
</g>
|
||||
<!-- .->bundle_combine -->
|
||||
<g id="edge16" class="edge"><title>.->bundle_combine</title>
|
||||
<path fill="none" stroke="black" d="M286.226,-219.503C274.338,-209.939 258.103,-196.876 244.237,-185.719"></path>
|
||||
<polygon fill="black" stroke="black" points="246.383,-182.954 236.398,-179.412 241.995,-188.408 246.383,-182.954"></polygon>
|
||||
<path fill="none" stroke="black" d="M299.774,-219.503C311.662,-209.939 327.897,-196.876 341.763,-185.719"></path>
|
||||
<polygon fill="black" stroke="black" points="344.005,-188.408 349.602,-179.412 339.617,-182.954 344.005,-188.408"></polygon>
|
||||
</g>
|
||||
<!-- tracker_download -->
|
||||
<g id="node24" class="node"><title>tracker_download</title>
|
||||
<ellipse fill="none" stroke="black" cx="569" cy="-162" rx="80.1284" ry="18"></ellipse>
|
||||
<text text-anchor="middle" x="569" y="-157.8" font-family="Times,serif" font-size="14.00">tracker_download</text>
|
||||
<ellipse fill="none" stroke="black" cx="544" cy="-162" rx="80.1284" ry="18"></ellipse>
|
||||
<text text-anchor="middle" x="544" y="-157.8" font-family="Times,serif" font-size="14.00">tracker_download</text>
|
||||
</g>
|
||||
<!-- .->tracker_download -->
|
||||
<g id="edge26" class="edge"><title>.->tracker_download</title>
|
||||
<path fill="none" stroke="black" d="M328.025,-226.415C369.14,-215.595 452.103,-193.762 509.094,-178.765"></path>
|
||||
<polygon fill="black" stroke="black" points="510.284,-182.071 519.064,-176.141 508.502,-175.301 510.284,-182.071"></polygon>
|
||||
<path fill="none" stroke="black" d="M307.554,-226.415C347.777,-215.627 428.818,-193.892 484.722,-178.898"></path>
|
||||
<polygon fill="black" stroke="black" points="485.753,-182.246 494.505,-176.275 483.94,-175.484 485.753,-182.246"></polygon>
|
||||
</g>
|
||||
<!-- index_app_names -->
|
||||
<g id="node7" class="node"><title>index_app_names</title>
|
||||
<ellipse fill="none" stroke="black" cx="407" cy="-90" rx="80.1456" ry="18"></ellipse>
|
||||
<text text-anchor="middle" x="407" y="-85.8" font-family="Times,serif" font-size="14.00">index_app_names</text>
|
||||
<ellipse fill="none" stroke="black" cx="196" cy="-90" rx="80.1456" ry="18"></ellipse>
|
||||
<text text-anchor="middle" x="196" y="-85.8" font-family="Times,serif" font-size="14.00">index_app_names</text>
|
||||
</g>
|
||||
<!-- bundle_download->index_app_names -->
|
||||
<g id="edge6" class="edge"><title>bundle_download->index_app_names</title>
|
||||
<path fill="none" stroke="black" d="M394.202,-143.697C396.096,-135.898 398.377,-126.509 400.484,-117.829"></path>
|
||||
<polygon fill="black" stroke="black" points="403.887,-118.648 402.846,-108.104 397.085,-116.996 403.887,-118.648"></polygon>
|
||||
<path fill="none" stroke="black" d="M196,-143.697C196,-135.983 196,-126.712 196,-118.112"></path>
|
||||
<polygon fill="black" stroke="black" points="199.5,-118.104 196,-108.104 192.5,-118.104 199.5,-118.104"></polygon>
|
||||
</g>
|
||||
<!-- html_bundle -->
|
||||
<g id="node9" class="node"><title>html_bundle</title>
|
||||
<ellipse fill="none" stroke="black" cx="334" cy="-18" rx="59.2871" ry="18"></ellipse>
|
||||
<text text-anchor="middle" x="334" y="-13.8" font-family="Times,serif" font-size="14.00">html_bundle</text>
|
||||
<ellipse fill="none" stroke="black" cx="261" cy="-18" rx="59.2871" ry="18"></ellipse>
|
||||
<text text-anchor="middle" x="261" y="-13.8" font-family="Times,serif" font-size="14.00">html_bundle</text>
|
||||
</g>
|
||||
<!-- index_app_names->html_bundle -->
|
||||
<g id="edge8" class="edge"><title>index_app_names->html_bundle</title>
|
||||
<path fill="none" stroke="black" d="M389.7,-72.411C380.427,-63.519 368.843,-52.4107 358.644,-42.6309"></path>
|
||||
<polygon fill="black" stroke="black" points="360.816,-39.8649 351.176,-35.4699 355.971,-44.9174 360.816,-39.8649"></polygon>
|
||||
<path fill="none" stroke="black" d="M211.735,-72.055C219.719,-63.4567 229.562,-52.8566 238.345,-43.3974"></path>
|
||||
<polygon fill="black" stroke="black" points="241.17,-45.4986 245.41,-35.789 236.041,-40.7354 241.17,-45.4986"></polygon>
|
||||
</g>
|
||||
<!-- html_index_apps -->
|
||||
<g id="node11" class="node"><title>html_index_apps</title>
|
||||
<ellipse fill="none" stroke="black" cx="489" cy="-18" rx="77.3345" ry="18"></ellipse>
|
||||
<text text-anchor="middle" x="489" y="-13.8" font-family="Times,serif" font-size="14.00">html_index_apps</text>
|
||||
<ellipse fill="none" stroke="black" cx="106" cy="-18" rx="77.3345" ry="18"></ellipse>
|
||||
<text text-anchor="middle" x="106" y="-13.8" font-family="Times,serif" font-size="14.00">html_index_apps</text>
|
||||
</g>
|
||||
<!-- index_app_names->html_index_apps -->
|
||||
<g id="edge10" class="edge"><title>index_app_names->html_index_apps</title>
|
||||
<path fill="none" stroke="black" d="M426.433,-72.411C437.053,-63.3446 450.373,-51.9742 461.99,-42.0572"></path>
|
||||
<polygon fill="black" stroke="black" points="464.373,-44.6246 469.707,-35.4699 459.829,-39.3006 464.373,-44.6246"></polygon>
|
||||
<path fill="none" stroke="black" d="M174.671,-72.411C162.902,-63.2575 148.114,-51.7553 135.278,-41.7715"></path>
|
||||
<polygon fill="black" stroke="black" points="137.218,-38.8467 127.176,-35.4699 132.92,-44.3721 137.218,-38.8467"></polygon>
|
||||
</g>
|
||||
<!-- html_index_domains -->
|
||||
<g id="node13" class="node"><title>html_index_domains</title>
|
||||
<ellipse fill="none" stroke="black" cx="164" cy="-18" rx="92.3709" ry="18"></ellipse>
|
||||
<text text-anchor="middle" x="164" y="-13.8" font-family="Times,serif" font-size="14.00">html_index_domains</text>
|
||||
<ellipse fill="none" stroke="black" cx="431" cy="-18" rx="92.3709" ry="18"></ellipse>
|
||||
<text text-anchor="middle" x="431" y="-13.8" font-family="Times,serif" font-size="14.00">html_index_domains</text>
|
||||
</g>
|
||||
<!-- index_app_names->html_index_domains -->
|
||||
<g id="edge12" class="edge"><title>index_app_names->html_index_domains</title>
|
||||
<path fill="none" stroke="black" d="M359.859,-75.4203C320.888,-64.1939 265.332,-48.1903 223.337,-36.093"></path>
|
||||
<polygon fill="black" stroke="black" points="224.092,-32.6682 213.514,-33.2633 222.154,-39.3947 224.092,-32.6682"></polygon>
|
||||
<path fill="none" stroke="black" d="M242.148,-75.2538C279.565,-64.1084 332.517,-48.3355 372.833,-36.3263"></path>
|
||||
<polygon fill="black" stroke="black" points="373.948,-39.6464 382.532,-33.4372 371.949,-32.9377 373.948,-39.6464"></polygon>
|
||||
</g>
|
||||
<!-- index_meta -->
|
||||
<g id="node14" class="node"><title>index_meta</title>
|
||||
<ellipse fill="none" stroke="black" cx="56" cy="-90" rx="56.1351" ry="18"></ellipse>
|
||||
<text text-anchor="middle" x="56" y="-85.8" font-family="Times,serif" font-size="14.00">index_meta</text>
|
||||
<ellipse fill="none" stroke="black" cx="351" cy="-90" rx="56.1351" ry="18"></ellipse>
|
||||
<text text-anchor="middle" x="351" y="-85.8" font-family="Times,serif" font-size="14.00">index_meta</text>
|
||||
</g>
|
||||
<!-- index_meta->html_bundle -->
|
||||
<g id="edge20" class="edge"><title>index_meta->html_bundle</title>
|
||||
<path fill="none" stroke="black" d="M330.578,-73.1159C318.466,-63.6958 302.928,-51.6106 289.609,-41.2514"></path>
|
||||
<polygon fill="black" stroke="black" points="291.695,-38.4402 281.653,-35.0635 287.398,-43.9657 291.695,-38.4402"></polygon>
|
||||
</g>
|
||||
<!-- index_meta->html_index_domains -->
|
||||
<g id="edge14" class="edge"><title>index_meta->html_index_domains</title>
|
||||
<path fill="none" stroke="black" d="M79.7011,-73.6382C94.3705,-64.1302 113.451,-51.7635 129.748,-41.2006"></path>
|
||||
<polygon fill="black" stroke="black" points="131.982,-43.9235 138.47,-35.5475 128.174,-38.0494 131.982,-43.9235"></polygon>
|
||||
</g>
|
||||
<!-- bundle_combine->html_bundle -->
|
||||
<g id="edge20" class="edge"><title>bundle_combine->html_bundle</title>
|
||||
<path fill="none" stroke="black" d="M238.83,-144.654C251.536,-134.888 267.134,-121.737 279,-108 295.683,-88.6865 310.622,-63.7629 320.705,-45.2056"></path>
|
||||
<polygon fill="black" stroke="black" points="323.917,-46.6183 325.518,-36.1451 317.736,-43.334 323.917,-46.6183"></polygon>
|
||||
<path fill="none" stroke="black" d="M369.555,-72.7646C379.906,-63.7076 392.977,-52.2705 404.399,-42.2756"></path>
|
||||
<polygon fill="black" stroke="black" points="406.769,-44.8525 411.99,-35.6334 402.16,-39.5845 406.769,-44.8525"></polygon>
|
||||
</g>
|
||||
<!-- bundle_combine->index_meta -->
|
||||
<g id="edge18" class="edge"><title>bundle_combine->index_meta</title>
|
||||
<path fill="none" stroke="black" d="M181.676,-145.983C156.897,-135.142 123.325,-120.455 97.1134,-108.987"></path>
|
||||
<polygon fill="black" stroke="black" points="98.3838,-105.723 87.8194,-104.921 95.5781,-112.136 98.3838,-105.723"></polygon>
|
||||
<path fill="none" stroke="black" d="M365.303,-143.697C363.187,-135.898 360.638,-126.509 358.282,-117.829"></path>
|
||||
<polygon fill="black" stroke="black" points="361.64,-116.838 355.643,-108.104 354.884,-118.672 361.64,-116.838"></polygon>
|
||||
</g>
|
||||
<!-- index_domains -->
|
||||
<g id="node21" class="node"><title>index_domains</title>
|
||||
<ellipse fill="none" stroke="black" cx="200" cy="-90" rx="70.0665" ry="18"></ellipse>
|
||||
<text text-anchor="middle" x="200" y="-85.8" font-family="Times,serif" font-size="14.00">index_domains</text>
|
||||
<ellipse fill="none" stroke="black" cx="495" cy="-90" rx="70.0665" ry="18"></ellipse>
|
||||
<text text-anchor="middle" x="495" y="-85.8" font-family="Times,serif" font-size="14.00">index_domains</text>
|
||||
</g>
|
||||
<!-- bundle_combine->index_domains -->
|
||||
<g id="edge22" class="edge"><title>bundle_combine->index_domains</title>
|
||||
<path fill="none" stroke="black" d="M212.045,-143.697C210.282,-135.983 208.163,-126.712 206.197,-118.112"></path>
|
||||
<polygon fill="black" stroke="black" points="209.55,-117.073 203.91,-108.104 202.726,-118.633 209.55,-117.073"></polygon>
|
||||
<path fill="none" stroke="black" d="M398.052,-145.291C415.824,-135.338 439,-122.36 458.236,-111.588"></path>
|
||||
<polygon fill="black" stroke="black" points="460.026,-114.597 467.041,-106.657 456.606,-108.489 460.026,-114.597"></polygon>
|
||||
</g>
|
||||
<!-- index_domains->html_index_domains -->
|
||||
<g id="edge24" class="edge"><title>index_domains->html_index_domains</title>
|
||||
<path fill="none" stroke="black" d="M191.285,-72.055C187.146,-64.0067 182.105,-54.2046 177.488,-45.2259"></path>
|
||||
<polygon fill="black" stroke="black" points="180.57,-43.5675 172.884,-36.2753 174.345,-46.7689 180.57,-43.5675"></polygon>
|
||||
<path fill="none" stroke="black" d="M479.833,-72.411C471.899,-63.7338 462.036,-52.946 453.255,-43.3418"></path>
|
||||
<polygon fill="black" stroke="black" points="455.834,-40.9748 446.503,-35.9562 450.667,-45.6982 455.834,-40.9748"></polygon>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 7.9 KiB After Width: | Height: | Size: 7.9 KiB |
Reference in New Issue
Block a user