diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..b1b3020 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# R wants HTML files to have UNIX line endings ie. just \n or LF +*.html text eol=lf \ No newline at end of file diff --git a/.gitignore b/.gitignore index 510e150..809c3fd 100644 --- a/.gitignore +++ b/.gitignore @@ -144,11 +144,22 @@ vignettes/*.pdf rsconnect/ /dags/r_scripts/credentials.json -/dags/galileo/*.csv +*.csv /data /.idea/ airflow.cfg *.avro /shiny/observatory/htpasswd -/tools/warcraider/*.warc -/shiny/observatory/*.csv +htpasswd +.htpasswd +*.warc +*.csv +*.rdata +*.xls +*.xlsx +*.gexf +*.graphml +Staticfile.auth +*.iml +*.ipr +*.iws diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..17e15f2 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,15 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Python: Current File", + "type": "python", + "request": "launch", + "program": "${file}", + "console": "integratedTerminal" + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..8e1c55b --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "python.linting.pylintEnabled": false, + "python.linting.pep8Enabled": false, + "python.linting.enabled": true, + "python.linting.flake8Enabled": true +} \ No newline at end of file diff --git a/AIRFLOW101.md b/AIRFLOW101.md new file mode 100644 index 0000000..265760c --- /dev/null +++ b/AIRFLOW101.md @@ -0,0 +1,130 @@ +# Airflow 101 + +## Our Environment + +Our analytics pipeline runs on open source [Apache Airflow](http://airflow.apache.org/tutorial.html) which is written in Python. This means we can deploy it to other clouds or inhouse if we need. + +We have some special configuration: +- using latest beta version composer-1.6.1-airflow-1.10.1 +- using Python 3 +- google-api-python-client, tablib, python-igraph, plotly pypi packages preinstalled +- slack_default and bigquery_default connection +- special docker image that includes google cloud SDK and R with tidyverse/ggplot2 +- sendgrid enabled to allow warning and other messages to be sent. + +## Getting Started +To access "Cloud Composer" (the Google branding for Airflow), visit https://console.cloud.google.com/composer/environments +From this page you can access the Airflow webserver and the DAGs folder + +Read https://cloud.google.com/composer/docs/ for more information. + +## How to write a new workflow + +### DAGs +Each pipeline is defined in a DAG file. (A Directed Acyclical Graph is a graph describing a process that goes step by step forward only with no infinite recursion or "cycles".) +DAG files are technically Python code but use some special keywords and operators to describe data processes. Each pipeline can have a schedule and a SLA (maximum expected run time). + +DAG files are made up of Tasks that run Operators and can draw from Connections (via Hooks) and Variables. Definitions @ http://airflow.apache.org/concepts.html + +Tutorials http://airflow.apache.org/tutorial.html and https://cloud.google.com/composer/docs/how-to/using/writing-dags and https://cloud.google.com/blog/products/gcp/how-to-aggregate-data-for-bigquery-using-apache-airflow + +Tips for designing a workflow: https://en.wikipedia.org/wiki/SOLID + +### Header + + +Set email_on_failure to True to send an email notification when an operator in the DAG fails. +``` +default_dag_args = { + + # Email whenever an Operator in the DAG fails. + 'email': models.Variable.get('email'), + 'email_on_failure': True, + 'email_on_retry': False, + 'retries': 1, + 'retry_delay': datetime.timedelta(minutes=5) +} +``` + +Schedule, start date and SLA + +**WARNING: if the start date is in the past, it will try to catch up running jobs for the schedule period (eg. daily) the first time the DAG is loaded ** + +If the task takes longer than the SLA, an alert email is triggered. + +``` +with models.DAG( + 'ga_quarterly_reporter', + schedule_interval=datetime.timedelta(days=90), + sla=datetime.timedelta(hours=1), + default_args=default_dag_args) as dag: +``` + + ### Variables + + Variables are configured via the webserver under Admin -> Variables. A variable can be a string, Python list/array or Python dict. + The second parameter of the .get() function is the default value if the variable isn't found. + You can use variables in the python string formatting functions https://docs.python.org/3/library/string.html#formatexamples +``` +from airflow import models + +'dataflow_default_options': { + 'project': models.Variable.get('GCP_PROJECT','dta-ga-bigquery'), + 'tempLocation': 'gs://staging.%s.appspot.com/' % models.Variable.get('GCP_PROJECT','dta-ga-bigquery') + } +``` + +### Operators + +Full listing at http://airflow.apache.org/_api/airflow/operators/index.html and http://airflow.apache.org/_api/airflow/contrib/operators/index.html includes operators for Bash scripts, JIRA, S3, SQL databases etc. + +**Our favourite operators:** + +- PythonOperator +http://airflow.apache.org/howto/operator/python.html + +- BigQueryOperator and BigQueryToCloudStorageOperator + +Our environment automatically has a connection to bigquery so no credentials are needed. + +http://airflow.apache.org/_api/airflow/contrib/operators/bigquery_operator/index.html + +- KubernetesPodOperator +Perfect for running an R script or a Python script that needs system packages like chart/graph rendering. + +We run a custom docker image with extra R packages described in docker/Dockerfile + +https://airflow.apache.org/_api/airflow/contrib/operators/kubernetes_pod_operator/index.html#airflow.contrib.operators.kubernetes_pod_operator.KubernetesPodOperator + +**Honorable Mentions:** + +- DataFlowOperator + +uses the google cloud branded implementation of Apache Beam, another +- SlackWebHookOperator + +- EmailOperator +Gmail seems to take 5 or 6 minutes to virus scan attachments before they appear. + + +## Dependencies and Deployment + +At the end of the file, in the indented "with DAG:" section you can define dependencies between operators (else they will all run concurrently): +``` +A >> B >> C + +or +A >> B +B >> C + +or + +A >> B +C << B + +``` + +Once you have a DAG, can drag drop it into the folder via the web browser and soon it will be visible in the webserver. When updating a DAG, there is also a Refresh (recycling icon) button. +You can either trigger the whole DAG or "clear" a task to make that task and all dependent tasks be retried. + +Once it is good, check it into Git! \ No newline at end of file diff --git a/README.md b/README.md index 265760c..aee5b39 100644 --- a/README.md +++ b/README.md @@ -1,130 +1,2 @@ -# Airflow 101 - -## Our Environment - -Our analytics pipeline runs on open source [Apache Airflow](http://airflow.apache.org/tutorial.html) which is written in Python. This means we can deploy it to other clouds or inhouse if we need. - -We have some special configuration: -- using latest beta version composer-1.6.1-airflow-1.10.1 -- using Python 3 -- google-api-python-client, tablib, python-igraph, plotly pypi packages preinstalled -- slack_default and bigquery_default connection -- special docker image that includes google cloud SDK and R with tidyverse/ggplot2 -- sendgrid enabled to allow warning and other messages to be sent. - -## Getting Started -To access "Cloud Composer" (the Google branding for Airflow), visit https://console.cloud.google.com/composer/environments -From this page you can access the Airflow webserver and the DAGs folder - -Read https://cloud.google.com/composer/docs/ for more information. - -## How to write a new workflow - -### DAGs -Each pipeline is defined in a DAG file. (A Directed Acyclical Graph is a graph describing a process that goes step by step forward only with no infinite recursion or "cycles".) -DAG files are technically Python code but use some special keywords and operators to describe data processes. Each pipeline can have a schedule and a SLA (maximum expected run time). - -DAG files are made up of Tasks that run Operators and can draw from Connections (via Hooks) and Variables. Definitions @ http://airflow.apache.org/concepts.html - -Tutorials http://airflow.apache.org/tutorial.html and https://cloud.google.com/composer/docs/how-to/using/writing-dags and https://cloud.google.com/blog/products/gcp/how-to-aggregate-data-for-bigquery-using-apache-airflow - -Tips for designing a workflow: https://en.wikipedia.org/wiki/SOLID - -### Header - - -Set email_on_failure to True to send an email notification when an operator in the DAG fails. -``` -default_dag_args = { - - # Email whenever an Operator in the DAG fails. - 'email': models.Variable.get('email'), - 'email_on_failure': True, - 'email_on_retry': False, - 'retries': 1, - 'retry_delay': datetime.timedelta(minutes=5) -} -``` - -Schedule, start date and SLA - -**WARNING: if the start date is in the past, it will try to catch up running jobs for the schedule period (eg. daily) the first time the DAG is loaded ** - -If the task takes longer than the SLA, an alert email is triggered. - -``` -with models.DAG( - 'ga_quarterly_reporter', - schedule_interval=datetime.timedelta(days=90), - sla=datetime.timedelta(hours=1), - default_args=default_dag_args) as dag: -``` - - ### Variables - - Variables are configured via the webserver under Admin -> Variables. A variable can be a string, Python list/array or Python dict. - The second parameter of the .get() function is the default value if the variable isn't found. - You can use variables in the python string formatting functions https://docs.python.org/3/library/string.html#formatexamples -``` -from airflow import models - -'dataflow_default_options': { - 'project': models.Variable.get('GCP_PROJECT','dta-ga-bigquery'), - 'tempLocation': 'gs://staging.%s.appspot.com/' % models.Variable.get('GCP_PROJECT','dta-ga-bigquery') - } -``` - -### Operators - -Full listing at http://airflow.apache.org/_api/airflow/operators/index.html and http://airflow.apache.org/_api/airflow/contrib/operators/index.html includes operators for Bash scripts, JIRA, S3, SQL databases etc. - -**Our favourite operators:** - -- PythonOperator -http://airflow.apache.org/howto/operator/python.html - -- BigQueryOperator and BigQueryToCloudStorageOperator - -Our environment automatically has a connection to bigquery so no credentials are needed. - -http://airflow.apache.org/_api/airflow/contrib/operators/bigquery_operator/index.html - -- KubernetesPodOperator -Perfect for running an R script or a Python script that needs system packages like chart/graph rendering. - -We run a custom docker image with extra R packages described in docker/Dockerfile - -https://airflow.apache.org/_api/airflow/contrib/operators/kubernetes_pod_operator/index.html#airflow.contrib.operators.kubernetes_pod_operator.KubernetesPodOperator - -**Honorable Mentions:** - -- DataFlowOperator - -uses the google cloud branded implementation of Apache Beam, another -- SlackWebHookOperator - -- EmailOperator -Gmail seems to take 5 or 6 minutes to virus scan attachments before they appear. - - -## Dependencies and Deployment - -At the end of the file, in the indented "with DAG:" section you can define dependencies between operators (else they will all run concurrently): -``` -A >> B >> C - -or -A >> B -B >> C - -or - -A >> B -C << B - -``` - -Once you have a DAG, can drag drop it into the folder via the web browser and soon it will be visible in the webserver. When updating a DAG, there is also a Refresh (recycling icon) button. -You can either trigger the whole DAG or "clear" a task to make that task and all dependent tasks be retried. - -Once it is good, check it into Git! \ No newline at end of file +# Observatory +To run the HTML version, download augov.gexf from /data on Google Cloud Storage, put it in html/observatory/data and run html/observatory/run.sh \ No newline at end of file diff --git a/dags/ga_benchmark.py b/dags/ga_benchmark.py index d3e70b8..cee4cfd 100644 --- a/dags/ga_benchmark.py +++ b/dags/ga_benchmark.py @@ -14,15 +14,12 @@ 'start_date': yesterday, } - with models.DAG( 'ga_benchmark', schedule_interval=datetime.timedelta(days=1), default_args=default_dag_args) as dag: - project_id = models.Variable.get('GCP_PROJECT','dta-ga-bigquery') + project_id = models.Variable.get('GCP_PROJECT', 'dta-ga-bigquery') - view_id = '69211100' - timestamp = '20190425' temp_table = 'benchmark_%s_%s' % (view_id, timestamp) query = """ CREATE TABLE `{{params.project_id}}.tmp.{{ params.temp_table }}` @@ -58,6 +55,7 @@ export_benchmark_to_gcs = bigquery_to_gcs.BigQueryToCloudStorageOperator( task_id='export_benchmark_to_gcs', source_project_dataset_table="%s.tmp.%s" % (project_id, temp_table), - destination_cloud_storage_uris=["gs://us-central1-maxious-airflow-64b78389-bucket/data/%s.csv" % (temp_table,)], + destination_cloud_storage_uris=["gs://%s/data/%s.csv" % ( + models.Variable.get('AIRFLOW_BUCKET', 'us-east1-dta-airflow-b3415db4-bucket'), temp_table)], export_format='CSV') query_benchmark >> export_benchmark_to_gcs diff --git a/dags/ga_daily_reporter.py b/dags/ga_daily_reporter.py index e1e46df..2d83c8b 100644 --- a/dags/ga_daily_reporter.py +++ b/dags/ga_daily_reporter.py @@ -3,7 +3,6 @@ import glob import os - from airflow import models from airflow.operators import python_operator from airflow.contrib.operators import slack_webhook_operator @@ -17,10 +16,10 @@ 'start_date': datetime.datetime(2019, 4, 26), # http://airflow.apache.org/_api/airflow/contrib/operators/dataflow_operator/index.html 'dataflow_default_options': { - 'project': models.Variable.get('GCP_PROJECT','dta-ga-bigquery'), + 'project': models.Variable.get('GCP_PROJECT', 'dta-ga-bigquery'), 'region': 'us-central1', 'zone': 'us-central1-b', - 'tempLocation': 'gs://staging.%s.appspot.com/' % models.Variable.get('GCP_PROJECT','dta-ga-bigquery') + 'tempLocation': 'gs://staging.%s.appspot.com/' % models.Variable.get('GCP_PROJECT', 'dta-ga-bigquery') } } @@ -32,12 +31,12 @@ def combine_tally(): from tablib import Dataset data = Dataset() - for f in glob.glob(DATA_DIR+'tally_69211100_20190425.csv-*'): + for f in glob.glob(DATA_DIR + 'tally_69211100_20190425.csv-*'): d = Dataset().load(open(f, 'rt').read()) for row in d: data.append(row) - with open(DATA_DIR+'tally_69211100_20190425.csv', 'wt') as f: + with open(DATA_DIR + 'tally_69211100_20190425.csv', 'wt') as f: f.write('path,hits\n') f.write(data.csv) @@ -45,36 +44,36 @@ def combine_tally(): def generate_plotly_chart(): from tablib import Dataset - df = Dataset().load(open(DATA_DIR+'tally_69211100_20190425.csv', 'r').read()).df.sort_values(by=['hits']) + df = Dataset().load(open(DATA_DIR + 'tally_69211100_20190425.csv', 'r').read()).df.sort_values(by=['hits']) df = df[df['hits'] > 30] import plotly import plotly.graph_objs as go plotly.offline.plot({ - "data": [go.Bar(x=df.path, y=df.hits)]}, filename=DATA_DIR+"temp-plot.html", auto_open=False) + "data": [go.Bar(x=df.path, y=df.hits)]}, filename=DATA_DIR + "temp-plot.html", auto_open=False) def generate_graph(): - import igraph g = igraph.Graph() g.add_vertices(3) - g.add_edges([(0,1), (1,2)]) + g.add_edges([(0, 1), (1, 2)]) print(g) - g.write_graphml(DATA_DIR+"social_network.graphml") + g.write_graphml(DATA_DIR + "social_network.graphml") def find_number_one(): from tablib import Dataset - df = Dataset().load(open(DATA_DIR+'tally_69211100_20190425.csv', 'r').read()).df.sort_values(by=['hits']) + df = Dataset().load(open(DATA_DIR + 'tally_69211100_20190425.csv', 'r').read()).df.sort_values(by=['hits']) return df.values[-1][0], df.values[-1][1] def tell_slack(context): o = slack_webhook_operator.SlackWebhookOperator(task_id="tell_slack", http_conn_id='slack_default', - message="Number one page today is %s (%s hits)" % (find_number_one())) + message="Number one page today is %s (%s hits)" % ( + find_number_one())) return o.execute(context) @@ -92,7 +91,9 @@ def tell_slack(context): # https://stackoverflow.com/questions/52054427/how-to-integrate-apache-airflow-with-slack tell_slack = slack_webhook_operator.SlackWebhookOperator(task_id="tell_slack", http_conn_id='slack_default', message="A new report is out: " - "https://storage.cloud.google.com/us-central1-maxious-airflow-64b78389-bucket/data/tally_69211100_20190425.csv") + "https://%s/data/tally_69211100_20190425.csv" % ( + models.Variable.get('AIRFLOW_BUCKET', + 'us-east1-dta-airflow-b3415db4-bucket'))) generate_graph = python_operator.PythonOperator( task_id='generate_graph', @@ -105,16 +106,19 @@ def tell_slack(context): from airflow.contrib.operators.kubernetes_pod_operator import KubernetesPodOperator kubetest = KubernetesPodOperator( - task_id='pod-ex-minimum', - name='pod-ex-minimum', - namespace='default', - image='gcr.io/%s/galileo' % models.Variable.get('GCP_PROJECT','dta-ga-bigquery'), - image_pull_policy="Always", - cmds=['bash', '-c'], - arguments=['gsutil cp gs://%s/data/tally_69211100_20190425.csv . && ' % models.Variable.get('AIRFLOW_BUCKET', 'us-east1-dta-airflow-b3415db4-bucket') + - 'gsutil cp gs://%s/dags/r_scripts/csvggplot.R . && ' % models.Variable.get('AIRFLOW_BUCKET', 'us-east1-dta-airflow-b3415db4-bucket') + - 'R -f csvggplot.R && ' - 'gsutil cp tally_69211100_20190425.png gs://%s/data/' % models.Variable.get('AIRFLOW_BUCKET', 'us-east1-dta-airflow-b3415db4-bucket') ],) + task_id='pod-ex-minimum', + name='pod-ex-minimum', + namespace='default', + image='gcr.io/%s/galileo' % models.Variable.get('GCP_PROJECT', 'dta-ga-bigquery'), + image_pull_policy="Always", + cmds=['bash', '-c'], + arguments=['gsutil cp gs://%s/data/tally_69211100_20190425.csv . && ' % models.Variable.get('AIRFLOW_BUCKET', + 'us-east1-dta-airflow-b3415db4-bucket') + + 'gsutil cp gs://%s/dags/r_scripts/csvggplot.R . && ' % models.Variable.get('AIRFLOW_BUCKET', + 'us-east1-dta-airflow-b3415db4-bucket') + + 'R -f csvggplot.R && ' + 'gsutil cp tally_69211100_20190425.png gs://%s/data/' % models.Variable.get('AIRFLOW_BUCKET', + 'us-east1-dta-airflow-b3415db4-bucket')], ) benchmark_tally >> combine_tally combine_tally >> generate_plotly_chart diff --git a/dags/ga_daily_reporter_test.py b/dags/ga_daily_reporter_test.py index 1970fa4..992b6cc 100644 --- a/dags/ga_daily_reporter_test.py +++ b/dags/ga_daily_reporter_test.py @@ -10,7 +10,7 @@ def test_dag_import(): if __package__ is None: import sys from os import path - sys.path.append( path.dirname( path.dirname( path.abspath(__file__) ) ) ) + sys.path.append(path.dirname(path.dirname(path.abspath(__file__)))) import ga_daily_reporter as module else: from . import ga_daily_reporter as module @@ -18,4 +18,4 @@ def test_dag_import(): if __name__ == '__main__': - test_dag_import() \ No newline at end of file + test_dag_import() diff --git a/dags/ga_quarterly_reporter.py b/dags/ga_quarterly_reporter.py index 19fdcdf..1641de8 100644 --- a/dags/ga_quarterly_reporter.py +++ b/dags/ga_quarterly_reporter.py @@ -23,7 +23,7 @@ def send_report(): datestamp = datetime.datetime.now().strftime('%d%b%Y') - report_file = DATA_DIR+'GA360-%s.csv' % datestamp + report_file = DATA_DIR + 'GA360-%s.csv' % datestamp table = Dataset().load(open(report_file, 'rt').read()).export('df').to_html() @@ -47,10 +47,13 @@ def send_report(): image='gcr.io/%s/galileo' % models.Variable.get('GCP_PROJECT', 'dta-ga-bigquery'), cmds=['bash', '-c'], image_pull_policy="Always", - arguments=['gsutil cp gs://%s/data/credentials.json . && '% models.Variable.get('AIRFLOW_BUCKET','us-east1-dta-airflow-b3415db4-bucket') + - 'gsutil cp gs://%s/dags/r_scripts/extractaccinfo.R . && ' % models.Variable.get('AIRFLOW_BUCKET','us-east1-dta-airflow-b3415db4-bucket') + + arguments=['gsutil cp gs://%s/data/credentials.json . && ' % models.Variable.get('AIRFLOW_BUCKET', + 'us-east1-dta-airflow-b3415db4-bucket') + + 'gsutil cp gs://%s/dags/r_scripts/extractaccinfo.R . && ' % models.Variable.get('AIRFLOW_BUCKET', + 'us-east1-dta-airflow-b3415db4-bucket') + 'R -f extractaccinfo.R && ' - 'gsutil cp GA360*.csv gs://%s/data/' % models.Variable.get('AIRFLOW_BUCKET','us-east1-dta-airflow-b3415db4-bucket') ]) + 'gsutil cp GA360*.csv gs://%s/data/' % models.Variable.get('AIRFLOW_BUCKET', + 'us-east1-dta-airflow-b3415db4-bucket')]) email_summary = PythonOperator( task_id='email_summary', diff --git a/dags/galileo/__init__.py b/dags/galileo/__init__.py index e69de29..d90ca6d 100644 --- a/dags/galileo/__init__.py +++ b/dags/galileo/__init__.py @@ -0,0 +1,5 @@ +import re + + +def domain_slug(domain): + return re.sub(r"http(s)|:|\/|www.?|\.", "", domain) diff --git a/dags/galileo/ga.py b/dags/galileo/ga.py index d623b74..a423492 100644 --- a/dags/galileo/ga.py +++ b/dags/galileo/ga.py @@ -1,25 +1,14 @@ -from apiclient.discovery import build -from oauth2client.service_account import ServiceAccountCredentials -import os import tablib -DATA_DIR = '/home/airflow/gcs/data/' -if not os.path.isdir(DATA_DIR): - DATA_DIR = '../../data/' - -def get_service(api_name, api_version, scopes): - credentials = ServiceAccountCredentials.from_json_keyfile_name( - DATA_DIR+'/credentials.json', scopes=scopes) - - # Build the service object. - service = build(api_name, api_version, credentials=credentials) - - return service +try: + from . import galileo +except ImportError: + import galileo def generate_accounts_views_index(): # Authenticate and construct service. - service = get_service( + service = galileo.get_service( api_name='analytics', api_version='v3', scopes=['https://www.googleapis.com/auth/analytics.readonly']) @@ -29,27 +18,71 @@ def generate_accounts_views_index(): accounts = service.management().accounts().list().execute() for account in accounts.get('items'): - #print 'account', account['id'], account['name'] + # print 'account', account['id'], account['name'] # Get a list of all the properties for the first account. properties = service.management().webproperties().list( accountId=account['id']).execute() for property in properties.get('items'): - #print ' property', property['id'],property['name'] + # print ' property', property['id'],property['name'] # Get a list of all views (profiles) for the first property. profiles = service.management().profiles().list( accountId=account['id'], webPropertyId=property['id']).execute() for view in profiles.get('items'): - #print ' view',view['id'], view['name'] + # print ' view',view['id'], view['name'] # return the first view (profile) id. data.append([account['id'], account['name'], property['id'], property['name'], property.get('level'), property.get('websiteUrl'), property.get('defaultProfileId'), view['id'], view['name']]) - with open(DATA_DIR+'/ga_accounts_views_index.csv', 'wb') as f: + with open(galileo.DATA_DIR + '/ga_accounts_views_index.csv', 'wt') as f: f.write(data.csv) +def get_events(name, view_id, category, action): + print('fetching', name, 'for', view_id) + service = galileo.get_service(api_name='analyticsreporting', api_version='v4', + scopes=['https://www.googleapis.com/auth/analytics.readonly']) + response = service.reports().batchGet( + body={ + 'reportRequests': [ + { + 'viewId': view_id, + 'dateRanges': [{'startDate': '30daysAgo', 'endDate': 'today'}], + 'metrics': [{'expression': 'ga:totalEvents'}], + 'dimensions': [{'name': 'ga:eventLabel'}], + 'orderBys': [{"fieldName": 'ga:totalEvents', "sortOrder": "DESCENDING"}], + 'filtersExpression': 'ga:totalEvents>10;ga:eventCategory==' + category + ';ga:eventAction==' + action, + 'pageSize': 100000 + }] + } + ).execute() + result = [] + for row in response.get('reports', [])[0].get('data', {}).get('rows', []): + if row: + # print(row['dimensions'][0], row['metrics'][0]['values'][0]) + result.append({"query": row['dimensions'][0], name: int(row['metrics'][0]['values'][0])}) + + return result + + if __name__ == '__main__': - generate_accounts_views_index() \ No newline at end of file + # generate_accounts_views_index() + + searches = get_events('impressions', '114274207', "ElasticSearch-Results", "Successful Search") + search_clicks = get_events('clicks', '114274207', "ElasticSearch-Results Clicks", "Page Result Click") + from collections import defaultdict + + d = defaultdict(dict) + for l in (searches, search_clicks): + for elem in l: + d[elem['query'].lower()].update(elem) + data = tablib.Dataset(headers=['query', 'impressions', 'clicks']) + for l in d.values(): + data.append((l['query'], l.get('impressions'), l.get('clicks'))) + import datetime + + with open(galileo.DATA_DIR + 'internalsearch_114274207_' + datetime.datetime.now().strftime('%Y%m%d') + '.csv', + 'wt') as f: + f.write(data.csv) diff --git a/dags/galileo/galileo.py b/dags/galileo/galileo.py new file mode 100644 index 0000000..882893f --- /dev/null +++ b/dags/galileo/galileo.py @@ -0,0 +1,26 @@ +import os +import re +from apiclient.discovery import build +from oauth2client.service_account import ServiceAccountCredentials + +DATA_DIR = '/home/airflow/gcs/data/' +if not os.path.isdir(DATA_DIR): + DATA_DIR = '../../data/' + + +def get_service(api_name, api_version, scopes): + if scopes == ['https://www.googleapis.com/auth/webmasters.readonly']: + credentials = ServiceAccountCredentials.from_json_keyfile_name( + DATA_DIR + '/test-credentials.json', scopes=scopes) + else: + credentials = ServiceAccountCredentials.from_json_keyfile_name( + DATA_DIR + '/credentials.json', scopes=scopes) + + # Build the service object. + service = build(api_name, api_version, credentials=credentials) + + return service + + +def domain_slug(domain): + return re.sub(r"http(s)|:|\/|www.?|\.", "", domain) diff --git a/dags/galileo/searchconsole.py b/dags/galileo/searchconsole.py new file mode 100644 index 0000000..ca5891e --- /dev/null +++ b/dags/galileo/searchconsole.py @@ -0,0 +1,81 @@ +import tablib +import datetime +import os + +try: + from . import galileo +except ImportError: + import galileo + + +def generate_web_search_query_report(property_uri, + days=10, + end_date=datetime.date.today()): + # Authenticate and construct service. + service = galileo.get_service( + api_name='webmasters', + api_version='v3', + scopes=['https://www.googleapis.com/auth/webmasters.readonly']) + start_date = (end_date - datetime.timedelta(days=days)).strftime('%Y-%m-%d') + end_date = end_date.strftime('%Y-%m-%d') + print(property_uri) + # First run a query to learn which dates we have data for. You should + # always check which days in a date range have data + # before running your main query. + # This query shows data for the entire range, grouped and sorted by day, + # descending; any days without data will be missing from the results. + request = { + 'startDate': start_date, + 'endDate': end_date, + 'dimensions': ['date'] + } + response = service.searchanalytics().query( + siteUrl=property_uri, body=request).execute() + # print(response) + # data_start_date = response['rows'][-days-1]['keys'][0] + data_start_date = response['rows'][0]['keys'][0] + data_end_date = response['rows'][-1]['keys'][0] + print("loading from", data_start_date, "to", data_end_date) # , "(", days, "days )") + data = tablib.Dataset() + data.headers = ["query", "page", "clicks", "impressions", + "click_thru_ratio", "search_result_position"] + page_start = 0 + last_rows = 1 + while last_rows > 0: + request = { + 'startDate': data_start_date, + 'endDate': data_end_date, + 'dimensions': ['query', 'page'], + 'rowLimit': 25000, + 'startRow': page_start + } + response = service.searchanalytics().query( + siteUrl=property_uri, body=request).execute() + + last_rows = 0 + if 'rows' in response: + for row in response['rows']: + last_rows += 1 + query = row['keys'][0].encode("ascii", errors="ignore").decode() + page = row['keys'][1].encode("ascii", errors="ignore").decode() + data.append([query, page, row['clicks'], + row['impressions'], row['ctr'], row['position']]) + print(page_start + last_rows, "received...") + page_start += 25000 + else: + print("done ", property_uri) + if not os.path.isdir(galileo.DATA_DIR + '/searchqueries'): + os.mkdir(galileo.DATA_DIR + '/searchqueries') + with open(galileo.DATA_DIR + '/searchqueries/{}_websearch_{}_{}.csv'.format( + galileo.domain_slug(property_uri), + data_start_date.replace('-', ''), + data_end_date.replace('-', ''), + ), 'wt', newline='') as f: + f.write(data.csv) + + +if __name__ == '__main__': + generate_search_query_report("https://data.gov.au") + generate_search_query_report("https://www.dta.gov.au") + generate_search_query_report("https://www.domainname.gov.au/") + generate_search_query_report("https://marketplace.service.gov.au") diff --git a/dags/galileo/unit_testing.py b/dags/galileo/unit_testing.py index 6b5f34f..b051a85 100644 --- a/dags/galileo/unit_testing.py +++ b/dags/galileo/unit_testing.py @@ -31,4 +31,4 @@ def assert_has_valid_dag(module): if no_dag_found: raise AssertionError('module does not contain a valid DAG') -# [END composer_dag_unit_testing] \ No newline at end of file +# [END composer_dag_unit_testing] diff --git a/dags/observatory.py b/dags/observatory.py index 4cd1b33..d23718e 100644 --- a/dags/observatory.py +++ b/dags/observatory.py @@ -32,9 +32,18 @@ image_pull_policy="Always", image=DOCKER_IMAGE, cmds=['bash', '-c'], - arguments=['mkdir deploy && ' + arguments=['git clone https://github.com/govau/GAlileo --depth=1 && ' + 'cp -rv GAlileo/shiny/observatory deploy &&' 'cd deploy && ' - 'gsutil cp -r gs://{GCS_BUCKET}/dags/shiny/observatory/* . && ' + 'gsutil cp -r gs://{GCS_BUCKET}/data/observatory/* . && ' 'htpasswd -b -c htpasswd observatory {HTPASSWD} && ' 'cf login -a https://api.system.y.cld.gov.au -u $CF_USERNAME -p $CF_PASSWORD && ' - 'cf push observatory'.format(GCS_BUCKET=GCS_BUCKET,HTPASSWD=htpasswd)]) + 'cf unmap-route observatory-green apps.y.cld.gov.au -n observatory &&' + 'cf v3-apply-manifest -f manifest.yml &&' + 'cf v3-push observatory-green &&' + 'cf map-route observatory-green apps.y.cld.gov.au -n observatory &&' + 'cf unmap-route observatory-blue apps.y.cld.gov.au -n observatory &&' + 'cf v3-push observatory-blue &&' + 'cf map-route observatory-blue apps.y.cld.gov.au -n observatory &&' + 'cf unmap-route observatory-blue apps.y.cld.gov.au -n observatory-green' + .format(GCS_BUCKET=GCS_BUCKET, HTPASSWD=htpasswd)]) diff --git a/dags/pipelines/benchmark_tally.py b/dags/pipelines/benchmark_tally.py index d8274b8..fad8670 100644 --- a/dags/pipelines/benchmark_tally.py +++ b/dags/pipelines/benchmark_tally.py @@ -9,17 +9,18 @@ from apache_beam.options.pipeline_options import PipelineOptions from apache_beam.options.pipeline_options import SetupOptions + def run(argv=None): parser = argparse.ArgumentParser() parser.add_argument('--input', dest='input', default='gs://us-central1-maxious-airflow-64b78389-bucket/data/benchmark_69211100_20190425.csv', - #'../../data/benchmark_69211100_20190425.csv', + # '../../data/benchmark_69211100_20190425.csv', help='Input file to process.') parser.add_argument('--output', dest='output', default='gs://us-central1-maxious-airflow-64b78389-bucket/data/tally_69211100_20190425.csv', - #'../../data/tally_69211100_20190425.csv', + # '../../data/tally_69211100_20190425.csv', help='Output file to write results to.') known_args, pipeline_args = parser.parse_known_args(argv) @@ -57,4 +58,4 @@ def format_result(path_count): if __name__ == '__main__': logging.getLogger().setLevel(logging.INFO) - run() \ No newline at end of file + run() diff --git a/dags/r_scripts/csvggplot.R b/dags/r_scripts/csvggplot.R index b3cb495..19308dd 100644 --- a/dags/r_scripts/csvggplot.R +++ b/dags/r_scripts/csvggplot.R @@ -4,7 +4,7 @@ library(tidyverse) d <- read.csv("tally_69211100_20190425.csv") d <- filter(d, hits > 1) d$path = str_wrap(d$path, width = 50) -p <- ggplot(d, aes(y=path, x=hits)) +geom_point() +p <- ggplot(d, aes(y = path, x = hits)) + geom_point() png("tally_69211100_20190425.png") print(p) dev.off() \ No newline at end of file diff --git a/dags/r_scripts/extractaccinfo.R b/dags/r_scripts/extractaccinfo.R index f5352db..4610c65 100644 --- a/dags/r_scripts/extractaccinfo.R +++ b/dags/r_scripts/extractaccinfo.R @@ -7,9 +7,9 @@ options(googleAuthR.scopes.selected = "https://www.googleapis.com/auth/analytics gar_auth_service("credentials.json") gg <- ga_account_list() %>% - select(accountId, internalWebPropertyId,websiteUrl, webPropertyId, level, type, viewId, viewName) %>% - filter(level=="PREMIUM" & type == "WEB") %>% + select(accountId, internalWebPropertyId, websiteUrl, webPropertyId, level, type, viewId, viewName) %>% + filter(level == "PREMIUM" & type == "WEB") %>% distinct(webPropertyId, .keep_all = TRUE) name <- paste0("GA360-", format(Sys.time(), '%d%b%Y'), ".csv") -write.csv(gg,name) +write.csv(gg, name) diff --git a/dags/web_search_reporter.py b/dags/web_search_reporter.py new file mode 100644 index 0000000..f4a8f24 --- /dev/null +++ b/dags/web_search_reporter.py @@ -0,0 +1,105 @@ +from __future__ import print_function +import datetime +import time +import os +import tablib + +from airflow import models +from airflow.operators import python_operator +from airflow.contrib.operators import bigquery_to_gcs +from airflow.contrib.operators import bigquery_operator + +from galileo import galileo, searchconsole, ga + +default_dag_args = { + # The start_date describes when a DAG is valid / can be run. Set this to a + # fixed point in time rather than dynamically, since it is evaluated every + # time a DAG is parsed. See: + # https://airflow.apache.org/faq.html#what-s-the-deal-with-start-date + 'start_date': datetime.datetime(2019, 7, 4), +} + + +def export_search_events(): + searches = ga.get_events('impressions', '114274207', "ElasticSearch-Results", "Successful Search") + search_clicks = ga.get_events('clicks', '114274207', "ElasticSearch-Results Clicks", "Page Result Click") + from collections import defaultdict + d = defaultdict(dict) + for l in (searches, search_clicks): + for elem in l: + d[elem['query'].lower()].update(elem) + data = tablib.Dataset(headers=['query', 'impressions', 'clicks']) + for l in d.values(): + data.append((l['query'], l.get('impressions'), l.get('clicks'))) + if not os.path.isdir(galileo.DATA_DIR + '/searchqueries'): + os.mkdir(galileo.DATA_DIR + '/searchqueries') + with open(galileo.DATA_DIR + '/searchqueries/114274207_internalsearch_' + datetime.datetime.now().strftime( + '%Y%m%d') + '.csv', + 'wt') as f: + f.write(data.csv) + + +with models.DAG( + 'search_reporter', + schedule_interval=datetime.timedelta(days=7), + default_args=default_dag_args) as dag: + event_searchqueries = python_operator.PythonOperator( + task_id='web_searchqueries_events', + python_callable=export_search_events) + + for domain in ["https://data.gov.au", "https://www.dta.gov.au", "https://www.domainname.gov.au/", + "https://marketplace.service.gov.au"]: + web_searchqueries = python_operator.PythonOperator( + task_id='web_searchqueries_' + galileo.domain_slug(domain), + python_callable=searchconsole.generate_web_search_query_report, + op_args=[domain]) + for d in [ + {"domain": "https://www.dta.gov.au", "view_id": 99993137, "search_param": "keys"}, + {"domain": "https://data.gov.au", "view_id": 69211100, "search_param": "q"}, + {"domain": "https://marketplace.service.gov.au", "view_id": 130142010, "search_param": "keyword"} + ]: + project_id = models.Variable.get('GCP_PROJECT', 'dta-ga-bigquery') + start = (datetime.date.today() - datetime.timedelta(days=30)).strftime("%Y%m%d") + end = (datetime.date.today() - datetime.timedelta(days=2)).strftime("%Y%m%d") + temp_table = '%s_internalsearch_%s' % (galileo.domain_slug(d['domain']), end) + + query = """ + CREATE TABLE `{{params.project_id}}.tmp.{{params.temp_table}}_{{ ts_nodash }}` + OPTIONS( + expiration_timestamp=TIMESTAMP_ADD(CURRENT_TIMESTAMP(), INTERVAL 1 HOUR) + ) AS + SELECT lower(replace(REGEXP_EXTRACT(page.pagePath, r"{{ params.search_param }}=(.*?)(?:&|$)"),"+"," ")) query, + count(*) impressions + FROM + `dta-ga-bigquery.{{params.view_id}}.ga_sessions_*`, + UNNEST(hits) + + WHERE + _TABLE_SUFFIX BETWEEN '{{params.start}}' AND '{{params.end}}' + AND REGEXP_CONTAINS(page.pagePath, r"{{ params.search_param }}=(.*?)(?:&|$)") + group by query + order by count(*) desc + """ + + query_internalsearch = bigquery_operator.BigQueryOperator( + task_id='query_internalsearch_' + galileo.domain_slug(d['domain']), + bql=query, use_legacy_sql=False, params={ + 'project_id': project_id, + 'view_id': d['view_id'], + 'start': start, + 'end': end, + 'temp_table': temp_table, + 'search_param': d['search_param'] + }) + export_internalsearch_to_gcs = bigquery_to_gcs.BigQueryToCloudStorageOperator( + task_id='export_internalsearch_to_gcs_' + galileo.domain_slug(d['domain']), + source_project_dataset_table="{{params.project_id}}.tmp.{{params.temp_table}}_{{ ts_nodash }}", + params= { + 'project_id': project_id, + 'temp_table': temp_table + }, + destination_cloud_storage_uris=[ + "gs://%s/data/searchqueries/%s.csv" % ( + models.Variable.get('AIRFLOW_BUCKET', 'us-east1-dta-airflow-b3415db4-bucket'), temp_table)], + export_format='CSV') + query_internalsearch >> export_internalsearch_to_gcs diff --git a/dags/wildebeest.py b/dags/wildebeest.py index a57894e..b23ff92 100644 --- a/dags/wildebeest.py +++ b/dags/wildebeest.py @@ -21,7 +21,7 @@ # to get view ids query "SELECT schema_name FROM INFORMATION_SCHEMA.SCHEMATA where schema_name < 'a'" view_ids = set(['34154705', '100180008', '88992271', '71597546', '101713735', '69211100', '86149663', - '99993137', '34938005', '70635257', '80842702', '101163468', '90974611', + '99993137', '34938005', '70635257', '80842702', '101163468', '90974611', '77664740', '104411629', '100832347', '95074916', '53715324', '95014024', '134969186', '31265425', '47586269', '95068310', '98362688', '104395490', '100095673', '5289745', '100136570', '77084214', '100095166', '85844330', '98349896', '129200625', '69522323', '98360372', '98349897']) @@ -103,10 +103,9 @@ def generate_url_query(view_ids): 'wildebeest', schedule_interval=datetime.timedelta(days=7), default_args=default_dag_args) as dag: - query, subqueries, temp_table = generate_host_query(view_ids) query_wildebeest_host = bigquery_operator.BigQueryOperator( - task_id='query_wildebeest_host' , + task_id='query_wildebeest_host', bql=query, use_legacy_sql=False, params={ 'project_id': project_id, 'temp_table': temp_table, diff --git a/docker/Dockerfile b/docker/Dockerfile index 64c5b40..e03503c 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -6,11 +6,10 @@ RUN sudo apt install -y curl gnupg RUN curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add - RUN sudo apt-get update ## install cloudfoundry tools -RUN curl -v -L -o cf-cli_amd64.deb 'https://cli.run.pivotal.io/stable?release=debian64&source=github' -RUN sudo dpkg -i cf-cli_amd64.deb +RUN curl -v -L -o cf-cli_amd64.deb 'https://cli.run.pivotal.io/stable?release=debian64&source=github' && sudo dpkg -i cf-cli_amd64.deb ## install google cloud SDK and common R packages -RUN sudo apt install -y google-cloud-sdk r-cran-ggplot2 r-cran-stringr apache2-utils +RUN sudo apt install -y google-cloud-sdk r-cran-ggplot2 r-cran-stringr r-cran-plyr r-cran-magrittr r-cran-lubridate apache2-utils ## install some R packages directly from CRAN RUN install2.r --error \ -r 'http://cran.rstudio.com' \ @@ -20,11 +19,11 @@ RUN install2.r --error \ gmailr \ googleCloudStorageR \ bigQueryR + RUN install2.r --error \ -r 'http://cran.rstudio.com' \ rsconnect - ## clean up RUN apt-get clean && rm -rf /var/lib/apt/lists/ && rm -rf /tmp/downloaded_packages/ /tmp/*.rds diff --git a/html/observatory/.eslintrc b/html/observatory/.eslintrc new file mode 100644 index 0000000..e0d8a85 --- /dev/null +++ b/html/observatory/.eslintrc @@ -0,0 +1,207 @@ + +{ + "parserOptions": { + "ecmaVersion": 2018, + "ecmaFeatures": { + "jsx": true + }, + "sourceType": "module" + }, + + "env": { + "es6": true, + "node": true + }, + + "plugins": [ + "import", + "node", + "promise", + "standard" + ], + + "globals": { + "document": false, + "navigator": false, + "window": false + }, + + "rules": { + "accessor-pairs": "error", + "arrow-spacing": ["error", { "before": true, "after": true }], + "block-spacing": ["error", "always"], + "brace-style": ["error", "1tbs", { "allowSingleLine": true }], + "camelcase": ["error", { "properties": "never" }], + "comma-dangle": ["error", { + "arrays": "never", + "objects": "never", + "imports": "never", + "exports": "never", + "functions": "never" + }], + "comma-spacing": ["error", { "before": false, "after": true }], + "comma-style": ["error", "last"], + "constructor-super": "error", + "curly": ["error", "multi-line"], + "dot-location": ["error", "property"], + "eol-last": "error", + "eqeqeq": ["error", "always", { "null": "ignore" }], + "func-call-spacing": ["error", "never"], + "generator-star-spacing": ["error", { "before": true, "after": true }], + "handle-callback-err": ["error", "^(err|error)$" ], + "indent": ["error", 2, { + "SwitchCase": 1, + "VariableDeclarator": 1, + "outerIIFEBody": 1, + "MemberExpression": 1, + "FunctionDeclaration": { "parameters": 1, "body": 1 }, + "FunctionExpression": { "parameters": 1, "body": 1 }, + "CallExpression": { "arguments": 1 }, + "ArrayExpression": 1, + "ObjectExpression": 1, + "ImportDeclaration": 1, + "flatTernaryExpressions": false, + "ignoreComments": false + }], + "key-spacing": ["error", { "beforeColon": false, "afterColon": true }], + "keyword-spacing": ["error", { "before": true, "after": true }], + "new-cap": ["error", { "newIsCap": true, "capIsNew": false }], + "new-parens": "error", + "no-array-constructor": "error", + "no-caller": "error", + "no-class-assign": "error", + "no-compare-neg-zero": "error", + "no-cond-assign": "error", + "no-const-assign": "error", + "no-constant-condition": ["error", { "checkLoops": false }], + "no-control-regex": "error", + "no-debugger": "error", + "no-delete-var": "error", + "no-dupe-args": "error", + "no-dupe-class-members": "error", + "no-dupe-keys": "error", + "no-duplicate-case": "error", + "no-empty-character-class": "error", + "no-empty-pattern": "error", + "no-eval": "error", + "no-ex-assign": "error", + "no-extend-native": "error", + "no-extra-bind": "error", + "no-extra-boolean-cast": "error", + "no-extra-parens": ["error", "functions"], + "no-fallthrough": "error", + "no-floating-decimal": "error", + "no-func-assign": "error", + "no-global-assign": "error", + "no-implied-eval": "error", + "no-inner-declarations": ["error", "functions"], + "no-invalid-regexp": "error", + "no-irregular-whitespace": "error", + "no-iterator": "error", + "no-label-var": "error", + "no-labels": ["error", { "allowLoop": false, "allowSwitch": false }], + "no-lone-blocks": "error", + "no-mixed-operators": ["error", { + "groups": [ + ["==", "!=", "===", "!==", ">", ">=", "<", "<="], + ["&&", "||"], + ["in", "instanceof"] + ], + "allowSamePrecedence": true + }], + "no-mixed-spaces-and-tabs": "error", + "no-multi-spaces": "error", + "no-multi-str": "error", + "no-multiple-empty-lines": ["error", { "max": 1, "maxEOF": 0 }], + "no-negated-in-lhs": "error", + "no-new": "error", + "no-new-func": "error", + "no-new-object": "error", + "no-new-require": "error", + "no-new-symbol": "error", + "no-new-wrappers": "error", + "no-obj-calls": "error", + "no-octal": "error", + "no-octal-escape": "error", + "no-path-concat": "error", + "no-proto": "error", + "no-redeclare": "error", + "no-regex-spaces": "error", + "no-return-assign": ["error", "except-parens"], + "no-return-await": "error", + "no-self-assign": "error", + "no-self-compare": "error", + "no-sequences": "error", + "no-shadow-restricted-names": "error", + "no-sparse-arrays": "error", + "no-tabs": "error", + "no-template-curly-in-string": "error", + "no-this-before-super": "error", + "no-throw-literal": "error", + "no-trailing-spaces": "error", + "no-undef": "error", + "no-undef-init": "error", + "no-unexpected-multiline": "error", + "no-unmodified-loop-condition": "error", + "no-unneeded-ternary": ["error", { "defaultAssignment": false }], + "no-unreachable": "error", + "no-unsafe-finally": "error", + "no-unsafe-negation": "error", + "no-unused-expressions": ["error", { "allowShortCircuit": true, "allowTernary": true, "allowTaggedTemplates": true }], + "no-unused-vars": ["error", { "vars": "all", "args": "none", "ignoreRestSiblings": true }], + "no-use-before-define": ["error", { "functions": false, "classes": false, "variables": false }], + "no-useless-call": "error", + "no-useless-computed-key": "error", + "no-useless-constructor": "error", + "no-useless-escape": "error", + "no-useless-rename": "error", + "no-useless-return": "error", + "no-whitespace-before-property": "error", + "no-with": "error", + "object-curly-spacing": ["error", "always"], + "object-property-newline": ["error", { "allowMultiplePropertiesPerLine": true }], + "one-var": ["error", { "initialized": "never" }], + "operator-linebreak": ["error", "after", { "overrides": { "?": "before", ":": "before" } }], + "padded-blocks": ["error", { "blocks": "never", "switches": "never", "classes": "never" }], + "prefer-promise-reject-errors": "error", + "quotes": ["error", "single", { "avoidEscape": true, "allowTemplateLiterals": true }], + "rest-spread-spacing": ["error", "never"], + "semi": ["error", "never"], + "semi-spacing": ["error", { "before": false, "after": true }], + "space-before-blocks": ["error", "always"], + "space-before-function-paren": ["error", "always"], + "space-in-parens": ["error", "never"], + "space-infix-ops": "error", + "space-unary-ops": ["error", { "words": true, "nonwords": false }], + "spaced-comment": ["error", "always", { + "line": { "markers": ["*package", "!", "/", ",", "="] }, + "block": { "balanced": true, "markers": ["*package", "!", ",", ":", "::", "flow-include"], "exceptions": ["*"] } + }], + "symbol-description": "error", + "template-curly-spacing": ["error", "never"], + "template-tag-spacing": ["error", "never"], + "unicode-bom": ["error", "never"], + "use-isnan": "error", + "valid-typeof": ["error", { "requireStringLiterals": true }], + "wrap-iife": ["error", "any", { "functionPrototypeMethods": true }], + "yield-star-spacing": ["error", "both"], + "yoda": ["error", "never"], + + "import/export": "error", + "import/first": "error", + "import/no-duplicates": "error", + "import/no-named-default": "error", + "import/no-webpack-loader-syntax": "error", + + "node/no-deprecated-api": "error", + "node/process-exit-as-throw": "error", + + "promise/param-names": "error", + + "standard/array-bracket-even-spacing": ["error", "either"], + "standard/computed-property-even-spacing": ["error", "even"], + "standard/no-callback-literal": "error", + "standard/object-curly-even-spacing": ["error", "either"] + } + } + \ No newline at end of file diff --git a/html/observatory/.htaccess b/html/observatory/.htaccess new file mode 100644 index 0000000..e2974bc --- /dev/null +++ b/html/observatory/.htaccess @@ -0,0 +1,2 @@ +AddType application/json json +AddType text/xml gexf diff --git a/html/observatory/Staticfile b/html/observatory/Staticfile new file mode 100644 index 0000000..e69de29 diff --git a/html/observatory/config_augov.json b/html/observatory/config_augov.json new file mode 100644 index 0000000..b96efde --- /dev/null +++ b/html/observatory/config_augov.json @@ -0,0 +1,37 @@ +{ + "type": "network", + "data":"augov.gexf", + "version": "1.0", + "agency": { + "name": "Digital Transformation Agency", + "lifeEvents": [], + "websites":[ + "www.dta.gov.au", + "www.homeaffairs.gov.au", + "www.humanservices.gov.au", + "www.australia.gov.au", + "www.passports.gov.au", + "www.casa.gov.au", + "www.apsc.gov.au", + "data.gov.au" + ] + }, + + "legend": { + "nodeLabel":"Government website", + "edgeLabel":"Link between two government websites", + "colorLabel":"Color is an automated grouping of sites" + }, + "features": { + "search": { + "enabled": true + }, + "hoverBehaviour": "dim", + "groupSelector": { + "enabled": true + } + }, + "informationPanel": { + "groupByEdgeDirection": false + } +} diff --git a/html/observatory/css/designsystem.min.css b/html/observatory/css/designsystem.min.css new file mode 100644 index 0000000..a291b64 --- /dev/null +++ b/html/observatory/css/designsystem.min.css @@ -0,0 +1,20 @@ + +/*! @gov.au/core v3.4.2 *//*! @gov.au/accordion v7.0.8 */@media print{.au-accordion{border-color:#000 !important;color:#000 !important}.au-accordion__title{background:#fff !important;color:#000 !important;border:1px !important}.au-accordion__title:after{display:none}.au-accordion__body-wrapper{border-color:#000 !important}.au-accordion__body{height:auto !important;display:block !important}}.au-accordion{font-size:16px;font-size:1rem;line-height:1.5;display:block;border:1px solid gray;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";color:#313131;padding:0}*+.au-accordion{margin-top:16px;margin-top:1rem}.au-accordion .au-accordion__title{background-color:#f5f5f5}.au-accordion.au-accordion--dark{border-color:#89afb8;color:#fff}.au-accordion.au-accordion--dark .au-accordion__title{background-color:#104f5f}.au-accordion+.au-accordion{margin-top:0;border-top:0}.au-body .au-accordion__title,.au-accordion__title{font-size:20px;font-size:1.25rem;line-height:1.2;padding:16px 40px 16px 16px;padding:1rem 2.5rem 1rem 1rem;width:100%;display:block;color:#00698f;text-decoration:underline;-webkit-text-decoration-skip:ink;text-decoration-skip-ink:auto;font-weight:bold;position:relative;-webkit-box-sizing:border-box;box-sizing:border-box;margin:0;cursor:pointer;border:none;text-align:left;font-family:inherit}.au-body .au-accordion__title:hover,.au-accordion__title:hover{text-decoration:none;color:#313131}.au-body .au-accordion__title:hover:after,.au-accordion__title:hover:after{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 128 128'%3E%3Cpath fill='%23313131' d='M64 0l64 64-16 16-64-64'/%3E%3Cpath fill='%23313131' d='M64 0l16 16-64 64L0 64'/%3E%3C/svg%3E")}.au-body .au-accordion__title:focus,.au-accordion__title:focus{outline:3px solid #9263DE;outline-offset:2px}.au-body .au-accordion__title::-moz-focus-inner,.au-accordion__title::-moz-focus-inner{border:0}.au-body .au-accordion__title:focus,.au-accordion__title:focus{z-index:100}.au-body .au-accordion__title::-webkit-details-marker,.au-accordion__title::-webkit-details-marker{display:none}.au-body .au-accordion__title:after,.au-accordion__title:after{content:' ';position:absolute;top:50%;margin-top:-8px;margin-top:-.5rem;right:16px;right:1rem;width:16px;width:1rem;height:16px;height:1rem;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 128 128'%3E%3Cpath fill='%2300698f' d='M64 0l64 64-16 16-64-64'/%3E%3Cpath fill='%2300698f' d='M64 0l16 16-64 64L0 64'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:center;z-index:101;-webkit-transition:-webkit-transform 0.25s ease-in;transition:-webkit-transform 0.25s ease-in;transition:transform 0.25s ease-in;transition:transform 0.25s ease-in, -webkit-transform 0.25s ease-in}.au-body .au-accordion__title.au-accordion--closed:after,.au-accordion__title.au-accordion--closed:after{-webkit-transform:rotate(-180deg);-ms-transform:rotate(-180deg);transform:rotate(-180deg)}.ie8 .au-body .au-accordion__title:after,.lt-ie8 .au-body .au-accordion__title:after,.ie8 .au-accordion__title:after,.lt-ie8 .au-accordion__title:after{content:' ▼ '}.ie8 .au-body .au-accordion__title.au-accordion--open:after,.lt-ie8 .au-body .au-accordion__title.au-accordion--open:after,.ie8 .au-accordion__title.au-accordion--open:after,.lt-ie8 .au-accordion__title.au-accordion--open:after{content:' ▲ '}.au-body.au-body--dark .au-accordion__title,.au-accordion.au-accordion--dark .au-accordion__title{color:#61daff}.au-body.au-body--dark .au-accordion__title:hover,.au-accordion.au-accordion--dark .au-accordion__title:hover{color:#fff}.au-body.au-body--dark .au-accordion__title:hover:after,.au-accordion.au-accordion--dark .au-accordion__title:hover:after{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 128 128'%3E %3Cpath fill='%23fff' d='M64 0l64 64-16 16-64-64'/%3E %3Cpath fill='%23fff' d='M64 0l16 16-64 64L0 64'/%3E%3C/svg%3E")}.au-body.au-body--dark .au-accordion__title:focus,.au-accordion.au-accordion--dark .au-accordion__title:focus{outline:3px solid #C390F9}.au-body.au-body--dark .au-accordion__title::-moz-focus-inner,.au-accordion.au-accordion--dark .au-accordion__title::-moz-focus-inner{border:0}.au-body.au-body--dark .au-accordion__title:after,.au-accordion.au-accordion--dark .au-accordion__title:after{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 128 128'%3E %3Cpath fill='%2361daff' d='M64 0l64 64-16 16-64-64'/%3E %3Cpath fill='%2361daff' d='M64 0l16 16-64 64L0 64'/%3E%3C/svg%3E")}.au-accordion__body{font-size:16px;font-size:1rem;line-height:1.5;overflow:hidden}.js .au-accordion__body.au-accordion--open{display:block;height:auto}.js .au-accordion__body.au-accordion--closed{display:none;height:0}.au-accordion__body-wrapper{padding:16px;padding:1rem;border-top:1px solid gray}.au-accordion--dark .au-accordion__body-wrapper{border-top:1px solid #89afb8}.au-accordion-group{list-style:none;padding:0}/*! @gov.au/body v2.2.0 */@media print{.au-body *,.au-body{text-shadow:none !important;color:#000 !important;background-color:transparent !important;-webkit-box-shadow:none !important;box-shadow:none !important;border-color:#000 !important}.au-body a,.au-body a:visited{text-decoration:underline}.au-body a[href]:after{content:" (" attr(href) ")" !important;display:inline !important}.au-body a[href^="javascript:"]:after,.au-body a[href^="#"]:after{content:"" !important}.au-body abbr[title]:after{content:" (" attr(title) ")"}.au-body pre,.au-body blockquote{border:1px solid #000;padding:6px;page-break-inside:avoid}.au-body thead{display:table-header-group}.au-body tr,.au-body img{page-break-inside:avoid}.au-body img{max-width:100% !important}.au-body p,.au-body h2,.au-body h3{orphans:3;widows:3}.au-body h2,.au-body h3{page-break-after:avoid}.au-body p a{word-wrap:break-word}.au-body select{background:#fff !important}}.au-body{font-size:16px;font-size:1rem;line-height:1.5;margin:0;-webkit-text-size-adjust:100%;-moz-text-size-adjust:100%;-ms-text-size-adjust:100%;text-size-adjust:100%;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";color:#313131;background-color:#fff}.au-body a{color:#00698f;text-decoration:underline;-webkit-text-decoration-skip:ink;text-decoration-skip-ink:auto}.au-body a:hover{color:#313131;text-decoration:none}.au-body a:focus{outline:3px solid #9263DE;outline-offset:2px}.au-body a::-moz-focus-inner{border:0}.au-body [tabindex="0"]:focus,.au-body :target{outline:3px solid #9263DE;outline-offset:2px}.au-body mark{color:#fff;background-color:#00698f}.au-body ::-moz-selection{color:#fff;background-color:rgba(0,105,143,0.99)}.au-body ::selection{color:#fff;background-color:rgba(0,105,143,0.99)}.au-body img::-moz-selection,.au-body video::-moz-selection,.au-body iframe::-moz-selection{background-color:rgba(0,105,143,0.75)}.au-body img::selection,.au-body video::selection,.au-body iframe::selection{background-color:rgba(0,105,143,0.75)}.au-body p{max-width:42em;margin:0}.au-body *+p{margin-top:24px;margin-top:1.5rem}.au-body ul:not([class]),.au-body ol:not([class]),.au-body dl:not([class]),.au-body pre{margin:0}.au-body *+ul:not([class]),.au-body *+ol:not([class]),.au-body *+dl:not([class]),.au-body *+pre{margin-top:24px;margin-top:1.5rem}.au-body ul:not([class])>li,.au-body ol:not([class])>li{margin-top:8px;margin-top:.5rem}.au-body ul:not([class])>li>ul:not([class]),.au-body ul:not([class])>li>ol:not([class]),.au-body ol:not([class])>li>ul:not([class]),.au-body ol:not([class])>li>ol:not([class]){margin-top:8px;margin-top:.5rem}.au-body ul:not([class])>ul:not([class]),.au-body ol:not([class])>ul:not([class]){list-style-type:disc}.au-body dl:not([class])>dd{margin-top:8px;margin-top:.5rem;padding-left:8px;padding-left:.5rem;margin-left:0;border-left:solid 1px}.au-body dl:not([class])>dt{margin-top:24px;margin-top:1.5rem;font-weight:bold}.au-body dl:not([class])>dt:first-of-type{margin-top:0}.au-body .written-by:after{content:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZlcnNpb249IjEiIHZpZXdCb3g9IjAgMCA2NTggMTgiPjx0ZXh0IHg9IjEzIiB5PSIxMyIgZm9udC1zaXplPSIxMyI+TWVzc3JzLCBEb20sIFBhZ2V5LCBUcmViLCBQYXQgYW5kIEtsZXBhcyBhcmUgcHJvdWQgdG8gcHJlc2VudCB0aGUgR09MRCBkZXNpZ24gc3lzdGVtLiAtIE1pc2NoaWVmIG1hbmFnZWQ8L3RleHQ+PC9zdmc+");color:#BADA55}.au-body em,.au-body i{font-style:italic}.au-body strong,.au-body b{font-weight:bold}.au-body small{font-size:14px;font-size:.875rem;line-height:1.42857143}.au-body s,.au-body del{text-decoration:line-through}.au-body ins{-webkit-text-decoration-line:underline;text-decoration-line:underline;-webkit-text-decoration-style:dashed;text-decoration-style:dashed;-webkit-text-decoration-skip:ink;text-decoration-skip-ink:auto}.au-body dfn{font-style:normal}.au-body abbr,.au-body abbr[title]{border-bottom:none;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}.au-body abbr[title]{cursor:help}.au-body a abbr{padding-bottom:1px}.au-body var{padding:0 1px;font-style:italic;font-family:serif}.au-body var sup,.au-body var sub{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";font-style:normal;padding:0 1px}.au-body sub,.au-body sup{font-size:14px;font-size:.875rem;line-height:1.14285714;position:relative;vertical-align:baseline}.au-body sub{bottom:-0.25em}.au-body sup{top:-0.5em}.au-body kbd,.au-body code,.au-body samp{font-size:14px;font-size:.875rem;line-height:1.42857143;padding:4px;padding:.25rem;font-family:"SFMono-Regular",Consolas,"Liberation Mono",Menlo,Courier,monospace;display:inline-block;border-radius:4px;background-color:#f5f5f5;color:#313131}.au-body pre{font-family:"SFMono-Regular",Consolas,"Liberation Mono",Menlo,Courier,monospace}.au-body pre code{padding:16px;padding:1rem;display:block;-moz-tab-size:4;-o-tab-size:4;tab-size:4}.au-body hr{-webkit-box-sizing:content-box;box-sizing:content-box;height:0;overflow:visible;border:none;border-top:1px solid gray;margin-bottom:24px;margin-bottom:1.5rem}.au-body *+hr{margin-top:24px;margin-top:1.5rem}.au-body.au-body--alt{background:#ebebeb}.au-body.au-body--alt kbd,.au-body.au-body--alt code,.au-body.au-body--alt samp{background-color:#e0e0e0}.au-body.au-body--dark{background:#135E70;color:#fff}.au-body.au-body--dark ::-moz-selection{color:#135E70;background-color:rgba(97,218,255,0.99)}.au-body.au-body--dark ::selection{color:#135E70;background-color:rgba(97,218,255,0.99)}.au-body.au-body--dark img::-moz-selection,.au-body.au-body--dark video::-moz-selection,.au-body.au-body--dark iframe::-moz-selection{background-color:rgba(97,218,255,0.75)}.au-body.au-body--dark img::selection,.au-body.au-body--dark video::selection,.au-body.au-body--dark iframe::selection{background-color:rgba(97,218,255,0.75)}.au-body.au-body--dark a{color:#61daff}.au-body.au-body--dark a:hover{color:#fff}.au-body.au-body--dark a:focus{outline:3px solid #C390F9}.au-body.au-body--dark a::-moz-focus-inner{border:0}.au-body.au-body--dark [tabindex="0"]:focus,.au-body.au-body--dark :target{outline:3px solid #C390F9}.au-body.au-body--dark mark{background-color:#61daff;color:#135E70}.au-body.au-body--dark hr{border-top-color:#89afb8}.au-body.au-body--dark code,.au-body.au-body--dark kbd,.au-body.au-body--dark samp{color:#fff;background-color:#104f5f}.au-body.au-body--dark.au-body--alt{background:#0d414d}.au-body.au-body--dark.au-body--alt code,.au-body.au-body--dark.au-body--alt kbd,.au-body.au-body--dark.au-body--alt samp{background-color:#0a323c}/*! @gov.au/link-list v3.0.8 */.au-link-list{font-size:16px;font-size:1rem;line-height:1.5;display:block;list-style-type:none;margin:0;padding:4px 0;padding:.25rem 0}.au-body .au-link-list{margin:0;padding:4px 0;padding:.25rem 0}.au-link-list>li{display:block;margin:4px;margin:.25rem}.au-link-list.au-link-list--inline{display:inline-block}.au-link-list.au-link-list--inline>li{display:inline-block}/*! @gov.au/breadcrumbs v3.0.5 */@media print{.au-breadcrumbs>.au-link-list>li:after{content:">" !important;background-image:none !important}}.au-breadcrumbs{font-size:14px;font-size:.875rem;line-height:1.14285714;width:100%;margin:0;color:#313131;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol"}*+.au-breadcrumbs{margin-top:16px;margin-top:1rem}@media (min-width: 768px){.au-breadcrumbs{display:inline-block}}.au-breadcrumbs>.au-link-list>li{margin:0}.au-breadcrumbs>.au-link-list>li:after{content:' ';display:inline-block;width:8px;width:.5rem;height:8px;height:.5rem;margin:0 8px;margin:0 .5rem;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 128 128'%3E%3Cpath fill='gray' d='M128 64l-64 64-16-16 64-64'/%3E%3Cpath fill='gray' d='M128 64l-16 16-64-64L64 0'/%3E%3C/svg%3E");background-size:100%;background-repeat:no-repeat}.au-breadcrumbs>.au-link-list>li:last-child:after{display:none}.ie8 .au-breadcrumbs>.au-link-list>li:after,.lt-ie8 .au-breadcrumbs>.au-link-list>li:after{content:' > ';display:inline-block}.au-breadcrumbs.au-breadcrumbs--dark{color:#fff}.au-breadcrumbs.au-breadcrumbs--dark>.au-link-list>li:not(:last-child):after{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 128 128'%3E%3Cpath fill='%2389afb8' d='M128 64l-64 64-16-16 64-64'/%3E%3Cpath fill='%2389afb8' d='M128 64l-16 16-64-64L64 0'/%3E%3C/svg%3E")}/*! @gov.au/buttons v3.0.7 */@media print{.au-btn{background-color:#fff !important;border:2px solid #000 !important;color:#000 !important;text-decoration:none !important}.au-btn[disabled]{background-color:#ccc !important;border:2px solid #ccc !important}.au-btn:disabled{background-color:#ccc !important;border:2px solid #ccc !important}}.au-btn,a.au-btn{font-size:16px;font-size:1rem;line-height:1.5;padding:8px 24px;padding:.5rem 1.5rem;display:inline-block;-webkit-appearance:none;-moz-appearance:none;appearance:none;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";color:#fff;text-decoration:none;border-radius:4px;background-color:#00698f;border:3px solid #00698f;cursor:pointer;vertical-align:middle;-webkit-transition:background 0.1s ease, border 0.1s ease, color 0.1s ease;transition:background 0.1s ease, border 0.1s ease, color 0.1s ease}.au-body .au-btn,.au-body a.au-btn{color:#fff;text-decoration:none}.au-btn.au-btn--block+.au-btn.au-btn--block,.au-btn.au-btn--block+a.au-btn.au-btn--block,a.au-btn.au-btn--block+.au-btn.au-btn--block,a.au-btn.au-btn--block+a.au-btn.au-btn--block{margin-top:8px;margin-top:.5rem}.au-btn:focus,a.au-btn:focus{outline:3px solid #9263DE;outline-offset:2px}.au-btn::-moz-focus-inner,a.au-btn::-moz-focus-inner{border:0}.au-btn:focus,a.au-btn:focus{border-radius:0}.au-btn[disabled],a.au-btn[disabled]{cursor:not-allowed;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=30)";opacity:0.3}.au-btn:disabled,a.au-btn:disabled{cursor:not-allowed;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=30)";opacity:0.3}.au-btn:hover:not(:disabled),a.au-btn:hover:not(:disabled){background-color:#313131;border-color:#313131;text-decoration:underline;color:#fff}.ie8 .au-btn:hover,.ie8 a.au-btn:hover{background-color:#313131;border-color:#313131;color:#fff;text-decoration:underline}.au-btn.au-btn--dark,a.au-btn.au-btn--dark{color:#135E70;background-color:#61daff;border-color:#61daff}.au-body .au-btn.au-btn--dark,.au-body a.au-btn.au-btn--dark{color:#135E70}.au-btn.au-btn--dark:hover:not(:disabled),a.au-btn.au-btn--dark:hover:not(:disabled){color:#135E70;border-color:#fff;background-color:#fff}.ie8 .au-btn.au-btn--dark:hover,.ie8 a.au-btn.au-btn--dark:hover{color:#135E70;border-color:#fff;background-color:#fff}.au-btn.au-btn--dark:focus,a.au-btn.au-btn--dark:focus{outline:3px solid #C390F9}.au-btn.au-btn--dark::-moz-focus-inner,a.au-btn.au-btn--dark::-moz-focus-inner{border:0}.au-btn.au-btn--secondary,a.au-btn.au-btn--secondary{color:#00698f;background-color:transparent;border-color:#00698f}.au-body .au-btn.au-btn--secondary,.au-body a.au-btn.au-btn--secondary{color:#00698f}.ie8 .au-body .au-btn.au-btn--secondary:hover,.ie8 .au-body a.au-btn.au-btn--secondary:hover{color:#fff}.au-btn.au-btn--secondary:hover:not(:disabled),a.au-btn.au-btn--secondary:hover:not(:disabled){background-color:transparent;border-color:#313131;color:#313131}.au-btn.au-btn--secondary.au-btn--dark,a.au-btn.au-btn--secondary.au-btn--dark{border-color:#61daff;color:#61daff}.au-btn.au-btn--secondary.au-btn--dark:hover:not(:disabled),a.au-btn.au-btn--secondary.au-btn--dark:hover:not(:disabled){border-color:#fff;color:#fff}.ie8 .au-body .au-btn.au-btn--secondary.au-btn--dark:hover,.ie8 .au-body a.au-btn.au-btn--secondary.au-btn--dark:hover{color:#135E70}.au-btn.au-btn--tertiary,a.au-btn.au-btn--tertiary{color:#00698f;background-color:transparent;border-color:transparent;text-decoration:underline}.au-btn.au-btn--tertiary:hover:not(:disabled),a.au-btn.au-btn--tertiary:hover:not(:disabled){background-color:transparent;color:#313131;border-color:transparent;text-decoration:none}.au-btn.au-btn--tertiary.au-btn--dark,a.au-btn.au-btn--tertiary.au-btn--dark{color:#61daff}.au-btn.au-btn--tertiary.au-btn--dark:hover:not(:disabled),a.au-btn.au-btn--tertiary.au-btn--dark:hover:not(:disabled){color:#fff}.au-btn.au-btn--pride,a.au-btn.au-btn--pride{background:-webkit-gradient(linear, left top, left bottom, color-stop(16.66666667%, rgba(255,62,24,0.5)), color-stop(16.66666667%, rgba(252,154,0,0.5)), color-stop(33.33333333%, rgba(252,154,0,0.52)), color-stop(33.33333333%, rgba(255,216,0,0.5)), color-stop(33.33333333%, rgba(255,216,0,0.5)), color-stop(50%, rgba(255,216,0,0.5)), color-stop(50%, rgba(57,234,124,0.5)), color-stop(66.66666667%, rgba(57,234,124,0.5)), color-stop(66.66666667%, rgba(11,178,255,0.5)), color-stop(83.33333333%, rgba(11,178,255,0.5)), color-stop(83.33333333%, rgba(152,90,255,0.5)));background:linear-gradient(to bottom, rgba(255,62,24,0.5) 16.66666667%, rgba(252,154,0,0.5) 16.66666667%, rgba(252,154,0,0.52) 33.33333333%, rgba(255,216,0,0.5) 33.33333333%, rgba(255,216,0,0.5) 33.33333333%, rgba(255,216,0,0.5) 50%, rgba(57,234,124,0.5) 50%, rgba(57,234,124,0.5) 66.66666667%, rgba(11,178,255,0.5) 66.66666667%, rgba(11,178,255,0.5) 83.33333333%, rgba(152,90,255,0.5) 83.33333333%);color:#313131}.au-btn.au-btn--block,a.au-btn.au-btn--block{display:block;width:100%;-webkit-box-sizing:border-box;box-sizing:border-box;text-align:center}/*! @gov.au/cta-link v2.2.0 */@media print{.au-cta-link{color:#000 !important}.au-cta-link:after{background-image:none !important;content:' > ' !important;border:none !important;-webkit-transform:rotate(0deg) !important;-ms-transform:rotate(0deg) !important;transform:rotate(0deg) !important}}.au-cta-link{font-size:20px;font-size:1.25rem;line-height:1.6;margin-top:16px;margin-top:1rem;font-weight:bold;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";color:#00698f;-webkit-appearance:none;-moz-appearance:none;appearance:none;background:transparent;border:none;padding:0;cursor:pointer;text-decoration:underline;-webkit-text-decoration-skip:ink;text-decoration-skip-ink:auto}.au-cta-link:focus{outline:3px solid #9263DE;outline-offset:2px}.au-cta-link::-moz-focus-inner{border:0}.au-cta-link:after{content:' ';width:16px;width:1rem;height:16px;height:1rem;margin:0 4px 0 3px;margin:0 .25rem 0 .2rem;-webkit-transition:margin 0.2s ease;transition:margin 0.2s ease;display:inline-block;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 128 128'%3E%3Cpath fill='%2300698f' d='M128 64l-64 64-16-16 64-64'/%3E%3Cpath fill='%2300698f' d='M128 64l-16 16-64-64L64 0'/%3E%3C/svg%3E")}.ie8 .au-cta-link:after,.lt-ie8 .au-cta-link:after{content:' > '}.au-cta-link:hover{color:#313131;text-decoration:none}.au-cta-link:hover:after{margin-left:6px;margin-left:.4rem;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 128 128'%3E%3Cpath fill='%23313131' d='M128 64l-64 64-16-16 64-64'/%3E%3Cpath fill='%23313131' d='M128 64l-16 16-64-64L64 0'/%3E%3C/svg%3E")}.au-cta-link.au-cta-link--dark{color:#61daff}.au-cta-link.au-cta-link--dark:focus{outline:3px solid #C390F9}.au-cta-link.au-cta-link--dark::-moz-focus-inner{border:0}.au-cta-link.au-cta-link--dark:after{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 128 128'%3E%3Cpath fill='%2361daff' d='M128 64l-64 64-16-16 64-64'/%3E%3Cpath fill='%2361daff' d='M128 64l-16 16-64-64L64 0'/%3E%3C/svg%3E")}.au-cta-link.au-cta-link--dark:hover{color:#fff}.au-cta-link.au-cta-link--dark:hover:after{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 128 128'%3E%3Cpath fill='%23fff' d='M128 64l-64 64-16-16 64-64'/%3E%3Cpath fill='%23fff' d='M128 64l-16 16-64-64L64 0'/%3E%3C/svg%3E")}/*! @gov.au/callout v3.0.2 */@media print{.au-callout{border-left-width:16px !important;border-left-width:1rem !important;border:1px solid #000 !important;color:#000 !important;background-color:transparent !important}}.au-callout{font-size:16px;font-size:1rem;line-height:1.5;padding:24px;padding:1.5rem;border-left:4px solid gray;border-left:.25rem solid gray;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";color:#313131;background-color:#f5f5f5;word-wrap:break-word}*+.au-callout{margin-top:32px;margin-top:2rem}.au-callout p{margin:0}.au-callout *+p{margin-top:16px;margin-top:1rem}.au-callout+p{margin-top:32px;margin-top:2rem}.au-callout.au-callout--dark{color:#fff;border-color:#89afb8;background-color:#104f5f}.au-callout.au-callout--alt{background-color:#e0e0e0}.au-callout.au-callout--dark.au-callout--alt{background-color:#0a323c}.au-callout__heading{font-size:20px;font-size:1.25rem;line-height:1.6;margin:0}.au-callout__heading.au-callout__heading--sronly{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.au-callout__heading.au-callout__heading--sronly+*{margin-top:0}.au-callout--calendar-event{background-color:#f5f5f5}.au-callout--calendar-event__lede{font-size:16px;font-size:1rem;line-height:1;margin:0}.au-callout--calendar-event__time,.au-callout--calendar-event__name{font-size:32px;font-size:2rem;line-height:1.25}.au-callout--calendar-event__time{font-weight:bold}.au-callout--calendar-event__lede,.au-callout--calendar-event__time,.au-callout--calendar-event__name{display:block}*+.au-callout--calendar-event__time,*+.au-callout--calendar-event__name,*+.au-callout--calendar-event__lede{margin-top:8px;margin-top:.5rem}/*! @gov.au/control-input v3.0.1 */@media print{.au-control-input__text{color:#000 !important}.au-control-input__text:before,.au-control-input__text:after{display:none !important}}.au-control-input{display:inline-block;position:relative}.au-control-input.au-control-input--block{display:block}.au-control-input.au-control-input--block:before,.au-control-input.au-control-input--block:after{content:" ";display:table}.au-control-input.au-control-input--block:after{clear:both}.au-control-input.au-control-input--block+.au-control-input--block{margin-top:16px;margin-top:1rem}.au-control-input__input{position:absolute;left:8px;left:.5rem;top:8px;top:.5rem;cursor:pointer;margin:0}.au-control-input--small .au-control-input__input{left:4px;left:.25rem;top:4px;top:.25rem}.au-control-input__input+.au-control-input__text{cursor:pointer}.au-control-input__input:invalid+.au-control-input__text{background-color:#fdf2f2}.au-control-input__input:invalid+.au-control-input__text:after{border-color:#d60000}.au-control-input--invalid .au-control-input__input+.au-control-input__text{background-color:#fdf2f2}.au-control-input--invalid .au-control-input__input+.au-control-input__text:after{border-color:#d60000}.au-control-input--dark .au-control-input__input:invalid+.au-control-input__text{background-color:#30505f}.au-control-input--dark.au-control-input--invalid .au-control-input__input+.au-control-input__text{background-color:#30505f}.au-control-input--alt.au-control-input--invalid .au-control-input__input+.au-control-input__text{background-color:#f0d0d0}.au-control-input--dark.au-control-input--alt .au-control-input__input:invalid+.au-control-input__text{background-color:#2b3742}.au-control-input--alt.au-control-input--dark.au-control-input--invalid .au-control-input__input+.au-control-input__text{background-color:#2b3742}.au-control-input--valid .au-control-input__input+.au-control-input__text{background-color:#f3faf8}.au-control-input--valid .au-control-input__input+.au-control-input__text:after{border-color:#0b996c}.au-control-input--dark.au-control-input--valid .au-control-input__input+.au-control-input__text{background-color:#12676f}.au-control-input--alt.au-control-input--valid .au-control-input__input+.au-control-input__text{background-color:#d2e7e0}.au-control-input--alt.au-control-input--dark.au-control-input--valid .au-control-input__input+.au-control-input__text{background-color:#0d4e52}.au-control-input__input[type=radio]+.au-control-input__text:before,.au-control-input__input[type=radio]+.au-control-input__text:after{border-radius:50%}.au-control-input__input[disabled]{cursor:not-allowed}.au-control-input__input[disabled]+.au-control-input__text{cursor:not-allowed}.au-control-input__input[disabled]+.au-control-input__text{color:#636363}.au-control-input__input:disabled{cursor:not-allowed}.au-control-input__input:disabled+.au-control-input__text{cursor:not-allowed}.au-control-input__input:disabled+.au-control-input__text{color:#636363}.au-control-input--dark .au-control-input__input[disabled]+.au-control-input__text{color:#b8cfd4}.au-control-input--dark .au-control-input__input:disabled+.au-control-input__text{color:#b8cfd4}.au-control-input__input[type=checkbox]+.au-control-input__text:before{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Cpath fill='%23313131' d='M0,0h32v32H0V0z'/%3E%3Cpath fill='%23fff' d='M2,2h28v28H2V2z'/%3E%3C/svg%3E")}.au-control-input__input[type=checkbox]+.au-control-input__text:after{background-image:none}.au-control-input__input[type=checkbox]:checked+.au-control-input__text:after{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Cpath fill='%23313131' d='M25.6,11.4c0.2-0.2,0.2-0.5,0-0.7l-2.3-2.3c-0.2-0.2-0.5-0.2-0.7,0L14,17l-3.6-3.6c-0.2-0.2-0.5-0.2-0.7,0l-2.3,2.3 c-0.2,0.2-0.2,0.5,0,0.7l6.3,6.3c0.2,0.2,0.5,0.2,0.7,0L25.6,11.4L25.6,11.4z'/%3E%3C/svg%3E")}.au-control-input--alt .au-control-input__input[type=checkbox]+.au-control-input__text:before{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Cpath fill='%23313131' d='M0,0h32v32H0V0z'/%3E%3Cpath fill='%23ebebeb' d='M2,2h28v28H2V2z'/%3E%3C/svg%3E")}.au-control-input--alt .au-control-input__input[type=checkbox]:disabled+.au-control-input__text:before{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Cpath fill='%23cecece' d='M0,0h32v32H0V0z'/%3E%3Cpath fill='%23e0e0e0' d='M2,2h28v28H2V2z'/%3E%3C/svg%3E")}.au-control-input__input[type=checkbox]:disabled+.au-control-input__text:before{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Cpath fill='%23cecece' d='M0,0h32v32H0V0z'/%3E%3Cpath fill='%23ebebeb' d='M2,2h28v28H2V2z'/%3E%3C/svg%3E")}.au-control-input__input[type=checkbox]:disabled:checked+.au-control-input__text:after{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Cpath fill='%23cecece' d='M25.6,11.4c0.2-0.2,0.2-0.5,0-0.7l-2.3-2.3c-0.2-0.2-0.5-0.2-0.7,0L14,17l-3.6-3.6c-0.2-0.2-0.5-0.2-0.7,0l-2.3,2.3 c-0.2,0.2-0.2,0.5,0,0.7l6.3,6.3c0.2,0.2,0.5,0.2,0.7,0L25.6,11.4L25.6,11.4z'/%3E%3C/svg%3E")}.au-control-input__input[type=checkbox]:focus+.au-control-input__text:before{outline:3px solid #9263DE;outline-offset:2px;outline-offset:2px}.au-control-input--dark .au-control-input__input[type=checkbox]+.au-control-input__text:before{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Cpath fill='%23fff' d='M0,0h32v32H0V0z'/%3E%3Cpath fill='%23135E70' d='M2,2h28v28H2V2z'/%3E%3C/svg%3E")}.au-control-input--dark .au-control-input__input[type=checkbox]:checked+.au-control-input__text:after{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Cpath fill='%23fff' d='M25.6,11.4c0.2-0.2,0.2-0.5,0-0.7l-2.3-2.3c-0.2-0.2-0.5-0.2-0.7,0L14,17l-3.6-3.6c-0.2-0.2-0.5-0.2-0.7,0l-2.3,2.3 c-0.2,0.2-0.2,0.5,0,0.7l6.3,6.3c0.2,0.2,0.5,0.2,0.7,0L25.6,11.4L25.6,11.4z'/%3E%3C/svg%3E")}.au-control-input--dark .au-control-input__input[type=checkbox]:disabled+.au-control-input__text:before{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Cpath fill='%2340727f' d='M0,0h32v32H0V0z'/%3E%3Cpath fill='%23104f5f' d='M2,2h28v28H2V2z'/%3E%3C/svg%3E")}.au-control-input--dark .au-control-input__input[type=checkbox]:disabled:checked+.au-control-input__text:after{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Cpath fill='%2340727f' d='M25.6,11.4c0.2-0.2,0.2-0.5,0-0.7l-2.3-2.3c-0.2-0.2-0.5-0.2-0.7,0L14,17l-3.6-3.6c-0.2-0.2-0.5-0.2-0.7,0l-2.3,2.3 c-0.2,0.2-0.2,0.5,0,0.7l6.3,6.3c0.2,0.2,0.5,0.2,0.7,0L25.6,11.4L25.6,11.4z'/%3E%3C/svg%3E")}.au-control-input--dark .au-control-input__input[type=checkbox]:focus+.au-control-input__text:before{outline:3px solid #C390F9;outline-offset:2px}.au-control-input--alt.au-control-input--dark .au-control-input__input[type=checkbox]+.au-control-input__text:before{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Cpath fill='%23fff' d='M0,0h32v32H0V0z'/%3E%3Cpath fill='%230d414d' d='M2,2h28v28H2V2z'/%3E%3C/svg%3E")}.au-control-input--alt.au-control-input--dark .au-control-input__input[type=checkbox]:disabled+.au-control-input__text:before{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Cpath fill='%233d6771' d='M0,0h32v32H0V0z'/%3E%3Cpath fill='%230a323c' d='M2,2h28v28H2V2z'/%3E%3C/svg%3E")}.au-control-input--alt.au-control-input--dark .au-control-input__input[type=checkbox]:disabled:checked+.au-control-input__text:after{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Cpath fill='%233d6771' d='M25.6,11.4c0.2-0.2,0.2-0.5,0-0.7l-2.3-2.3c-0.2-0.2-0.5-0.2-0.7,0L14,17l-3.6-3.6c-0.2-0.2-0.5-0.2-0.7,0l-2.3,2.3 c-0.2,0.2-0.2,0.5,0,0.7l6.3,6.3c0.2,0.2,0.5,0.2,0.7,0L25.6,11.4L25.6,11.4z'/%3E%3C/svg%3E")}.au-control-input__input[type=radio]+.au-control-input__text:before{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Ccircle fill='%23313131' cx='16' cy='16' r='16'/%3E%3Ccircle fill='%23fff' cx='16' cy='16' r='14'/%3E%3C/svg%3E")}.au-control-input__input[type=radio]+.au-control-input__text:after{background-image:none}.au-control-input__input[type=radio]:checked+.au-control-input__text:after{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Ccircle fill='%23313131' cx='16' cy='16' r='11'/%3E%3C/svg%3E")}.au-control-input--alt .au-control-input__input[type=radio]+.au-control-input__text:before{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Ccircle fill='%23313131' cx='16' cy='16' r='16'/%3E%3Ccircle fill='%23ebebeb' cx='16' cy='16' r='14'/%3E%3C/svg%3E")}.au-control-input--alt .au-control-input__input[type=radio]:disabled+.au-control-input__text:before{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Ccircle fill='%23cecece' cx='16' cy='16' r='16'/%3E%3Ccircle fill='%23e0e0e0' cx='16' cy='16' r='14'/%3E%3C/svg%3E")}.au-control-input__input[type=radio]:disabled+.au-control-input__text:before{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Ccircle fill='%23cecece' cx='16' cy='16' r='16'/%3E%3Ccircle fill='%23ebebeb' cx='16' cy='16' r='14'/%3E%3C/svg%3E")}.au-control-input__input[type=radio]:disabled:checked+.au-control-input__text:after{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Ccircle fill='%23cecece' cx='16' cy='16' r='11'/%3E%3C/svg%3E")}.au-control-input__input[type=radio]:focus+.au-control-input__text:before{-webkit-box-shadow:0 0 0 4px #9263DE;box-shadow:0 0 0 4px #9263DE;-webkit-box-shadow:0 0 0 .25rem #9263DE;box-shadow:0 0 0 .25rem #9263DE}.ie8 .au-control-input__input[type=radio]:focus+.au-control-input__text:before,.lt-ie8 .au-control-input__input[type=radio]:focus+.au-control-input__text:before{outline:3px solid #9263DE;outline-offset:2px;outline-offset:2px}.au-control-input--dark .au-control-input__input[type=radio]+.au-control-input__text:before{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Ccircle fill='%23fff' cx='16' cy='16' r='16'/%3E%3Ccircle fill='%23135E70' cx='16' cy='16' r='14'/%3E%3C/svg%3E")}.au-control-input--dark .au-control-input__input[type=radio]:checked+.au-control-input__text:after{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Ccircle fill='%23fff' cx='16' cy='16' r='11'/%3E%3C/svg%3E")}.au-control-input--dark .au-control-input__input[type=radio]:disabled+.au-control-input__text:before{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Ccircle fill='%2340727f' cx='16' cy='16' r='16'/%3E%3Ccircle fill='%23104f5f' cx='16' cy='16' r='14'/%3E%3C/svg%3E")}.au-control-input--dark .au-control-input__input[type=radio]:disabled:checked+.au-control-input__text:after{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Ccircle fill='%2340727f' cx='16' cy='16' r='11'/%3E%3C/svg%3E")}.au-control-input--dark .au-control-input__input[type=radio]:focus+.au-control-input__text:before{-webkit-box-shadow:0 0 0 4px #C390F9;box-shadow:0 0 0 4px #C390F9;-webkit-box-shadow:0 0 0 .25rem #C390F9;box-shadow:0 0 0 .25rem #C390F9}.ie8 .au-control-input--dark .au-control-input__input[type=radio]:focus+.au-control-input__text:before,.lt-ie8 .au-control-input--dark .au-control-input__input[type=radio]:focus+.au-control-input__text:before{outline:3px solid #C390F9;outline-offset:2px}.au-control-input--alt.au-control-input--dark .au-control-input__input[type=radio]+.au-control-input__text:before{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Ccircle fill='%23fff' cx='16' cy='16' r='16'/%3E%3Ccircle fill='%230d414d' cx='16' cy='16' r='14'/%3E%3C/svg%3E")}.au-control-input--alt.au-control-input--dark .au-control-input__input[type=radio]:disabled+.au-control-input__text:before{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Ccircle fill='%233d6771' cx='16' cy='16' r='16'/%3E%3Ccircle fill='%230a323c' cx='16' cy='16' r='14'/%3E%3C/svg%3E")}.au-control-input--alt.au-control-input--dark .au-control-input__input[type=radio]:disabled:checked+.au-control-input__text:after{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Ccircle fill='%233d6771' cx='16' cy='16' r='11'/%3E%3C/svg%3E")}.au-control-input__text{font-size:16px;font-size:1rem;line-height:1.5;padding:4px 8px 8px 40px;padding:.25rem .5rem .5rem 2.5rem;margin-right:16px;margin-right:1rem;display:block;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";color:#313131}.au-control-input__text:before,.au-control-input__text:after{width:38px;width:2.375rem;height:38px;height:2.375rem;content:' ';display:block;position:absolute;-webkit-box-sizing:border-box;box-sizing:border-box;background-repeat:no-repeat;z-index:100;left:-3px;top:-3px;border:3px solid transparent}.au-control-input--small .au-control-input__text:before,.au-control-input--small .au-control-input__text:after{width:28px;width:1.75rem;height:28px;height:1.75rem}.au-control-input--small .au-control-input__text{padding:3px 8px 0 31px;padding:.2rem .5rem 0 1.95rem;margin-right:16px;margin-right:1rem;font-size:16px;font-size:1rem;line-height:1}.au-control-input__text:after{z-index:101}.au-control-input--dark .au-control-input__text{color:#fff}/*! @gov.au/direction-links v2.2.0 */@media print{.au-direction-link{color:#000 !important}.au-direction-link:after{content:'→' !important}.au-direction-link--left:before{content:'←' !important}.au-direction-link--up:after{content:'↑' !important}.au-direction-link--down:after{content:'↓' !important}}.au-direction-link{font-size:16px;font-size:1rem;line-height:1.5;display:inline-block;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";color:#00698f;-webkit-appearance:none;-moz-appearance:none;appearance:none;background:transparent;border:none;padding:0;cursor:pointer;text-decoration:underline;-webkit-text-decoration-skip:ink;text-decoration-skip-ink:auto}.au-direction-link:hover{text-decoration:none;color:#313131}.au-direction-link:focus{outline:3px solid #9263DE;outline-offset:2px}.au-direction-link::-moz-focus-inner{border:0}.au-direction-link.au-direction-link--dark{color:#61daff}.au-direction-link.au-direction-link--dark:hover{color:#fff}.au-direction-link.au-direction-link--dark:focus{outline:3px solid #C390F9}.au-direction-link.au-direction-link--dark::-moz-focus-inner{border:0}.au-direction-link:after{width:16px;width:1rem;height:16px;height:1rem;margin:0 0 0 4px;margin:0 0 0 .25rem;content:'→';display:inline-block;width:auto;height:auto}.au-direction-link--left:after{display:none}.au-direction-link--left:before{content:'←';display:inline-block;width:16px;width:1rem;height:16px;height:1rem;margin:0 4px 0 0;margin:0 .25rem 0 0}.au-direction-link--up:after{content:'↑'}.au-direction-link--down:after{content:'↓'}/*! @gov.au/footer v3.0.5 */@media print{.au-footer{color:#000 !important;background:#fff !important;border-color:#000 !important}}.au-footer{font-size:16px;font-size:1rem;line-height:1.5;padding:48px 0 48px;padding:3rem 0 3rem;border-top:4px solid gray;border-top:.25rem solid gray;background-color:#fff;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";color:#313131}.au-footer p:last-child{margin:0}.au-footer.au-footer--alt{background-color:#ebebeb}.au-footer.au-footer--dark{color:#fff;border-color:#89afb8;background-color:#135E70}.au-footer.au-footer--dark.au-footer--alt{background-color:#0d414d}.au-footer__navigation .au-link-list>li{margin-left:0}.au-footer__end{padding-top:16px;padding-top:1rem;margin-top:16px;margin-top:1rem;border-top:1px solid gray}.au-footer--dark .au-footer__end{border-top:1px solid #89afb8}/*! @gov.au/form v0.1.4 */.au-form-group--invalid{border-left:solid 5px #d60000;padding-left:15px}.au-form-group+.au-form-group{margin-top:20px;margin-top:1.25rem}.au-label{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";color:#313131;display:block;font-size:16px;font-size:1rem;line-height:1.5}.au-label+.au-select,.au-label+input,.au-label+textarea{margin-top:4px;margin-top:.25rem}.au-label--inline{display:inline-block}.au-label--inline+.au-select,.au-label--inline+input,.au-label--inline+textarea{margin-top:0}.au-label--dark{color:#fff}.au-hint-text{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";color:#6f777b;display:block;font-size:16px;font-size:1rem;line-height:1.5}*+.au-hint-text{margin-top:6px;margin-top:.4rem}.au-hint-text+.au-select,.au-hint-text+input,.au-hint-text+textarea{margin-top:4px;margin-top:.25rem}.au-hint-text--dark{color:#b8cfd4}.au-hint-text--alt{color:#61696B}.au-error-text{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";font-weight:bold;font-size:16px;font-size:1rem;line-height:1.5;color:#d60000;display:block}*+.au-error-text{margin-top:6px;margin-top:.4rem}.au-error-text+.au-select,.au-error-text+input,.au-error-text+textarea{margin-top:4px;margin-top:.25rem}.au-error-text--inline{display:inline-block}.au-error-text--inline+.au-select,.au-error-text--inline+input,.au-error-text--inline+textarea{margin-top:0}.au-error-text--hidden{display:none}.au-fieldset{margin:0;padding:0;border:0}.au-fieldset__legend{margin-bottom:12px;margin-bottom:.75rem}/*! @gov.au/grid-12 v2.1.0 */.au-grid .container{-webkit-box-sizing:border-box;box-sizing:border-box}@media (min-width: 768px){.au-grid .container{width:744px}}@media (min-width: 992px){.au-grid .container{width:968px}}@media (min-width: 1200px){.au-grid .container{width:1176px}}.au-grid .container,.au-grid .container-fluid{-webkit-box-sizing:border-box;box-sizing:border-box;margin-right:auto;margin-left:auto;padding-left:12px;padding-right:12px}.au-grid .container:before,.au-grid .container:after,.au-grid .container-fluid:before,.au-grid .container-fluid:after{content:" ";display:table}.au-grid .container:after,.au-grid .container-fluid:after{clear:both}.au-grid .row{margin-left:-12px;margin-right:-12px}.au-grid .row:before,.au-grid .row:after{content:" ";display:table}.au-grid .row:after{clear:both}.au-grid .col-xs-1,.au-grid .col-sm-1,.au-grid .col-md-1,.au-grid .col-lg-1,.au-grid .col-xs-2,.au-grid .col-sm-2,.au-grid .col-md-2,.au-grid .col-lg-2,.au-grid .col-xs-3,.au-grid .col-sm-3,.au-grid .col-md-3,.au-grid .col-lg-3,.au-grid .col-xs-4,.au-grid .col-sm-4,.au-grid .col-md-4,.au-grid .col-lg-4,.au-grid .col-xs-5,.au-grid .col-sm-5,.au-grid .col-md-5,.au-grid .col-lg-5,.au-grid .col-xs-6,.au-grid .col-sm-6,.au-grid .col-md-6,.au-grid .col-lg-6,.au-grid .col-xs-7,.au-grid .col-sm-7,.au-grid .col-md-7,.au-grid .col-lg-7,.au-grid .col-xs-8,.au-grid .col-sm-8,.au-grid .col-md-8,.au-grid .col-lg-8,.au-grid .col-xs-9,.au-grid .col-sm-9,.au-grid .col-md-9,.au-grid .col-lg-9,.au-grid .col-xs-10,.au-grid .col-sm-10,.au-grid .col-md-10,.au-grid .col-lg-10,.au-grid .col-xs-11,.au-grid .col-sm-11,.au-grid .col-md-11,.au-grid .col-lg-11,.au-grid .col-xs-12,.au-grid .col-sm-12,.au-grid .col-md-12,.au-grid .col-lg-12{-webkit-box-sizing:border-box;box-sizing:border-box;position:relative;min-height:1px;padding-left:12px;padding-right:12px}.au-grid .col-xs-1,.au-grid .col-xs-2,.au-grid .col-xs-3,.au-grid .col-xs-4,.au-grid .col-xs-5,.au-grid .col-xs-6,.au-grid .col-xs-7,.au-grid .col-xs-8,.au-grid .col-xs-9,.au-grid .col-xs-10,.au-grid .col-xs-11,.au-grid .col-xs-12{float:left}.au-grid .col-xs-1{width:8.33333333%}.au-grid .col-xs-2{width:16.66666667%}.au-grid .col-xs-3{width:25%}.au-grid .col-xs-4{width:33.33333333%}.au-grid .col-xs-5{width:41.66666667%}.au-grid .col-xs-6{width:50%}.au-grid .col-xs-7{width:58.33333333%}.au-grid .col-xs-8{width:66.66666667%}.au-grid .col-xs-9{width:75%}.au-grid .col-xs-10{width:83.33333333%}.au-grid .col-xs-11{width:91.66666667%}.au-grid .col-xs-12{width:100%}.au-grid .col-xs-pull-0{right:auto}.au-grid .col-xs-pull-1{right:8.33333333%}.au-grid .col-xs-pull-2{right:16.66666667%}.au-grid .col-xs-pull-3{right:25%}.au-grid .col-xs-pull-4{right:33.33333333%}.au-grid .col-xs-pull-5{right:41.66666667%}.au-grid .col-xs-pull-6{right:50%}.au-grid .col-xs-pull-7{right:58.33333333%}.au-grid .col-xs-pull-8{right:66.66666667%}.au-grid .col-xs-pull-9{right:75%}.au-grid .col-xs-pull-10{right:83.33333333%}.au-grid .col-xs-pull-11{right:91.66666667%}.au-grid .col-xs-pull-12{right:100%}.au-grid .col-xs-push-0{left:auto}.au-grid .col-xs-push-1{left:8.33333333%}.au-grid .col-xs-push-2{left:16.66666667%}.au-grid .col-xs-push-3{left:25%}.au-grid .col-xs-push-4{left:33.33333333%}.au-grid .col-xs-push-5{left:41.66666667%}.au-grid .col-xs-push-6{left:50%}.au-grid .col-xs-push-7{left:58.33333333%}.au-grid .col-xs-push-8{left:66.66666667%}.au-grid .col-xs-push-9{left:75%}.au-grid .col-xs-push-10{left:83.33333333%}.au-grid .col-xs-push-11{left:91.66666667%}.au-grid .col-xs-push-12{left:100%}.au-grid .col-xs-offset-0{margin-left:0%}.au-grid .col-xs-offset-1{margin-left:8.33333333%}.au-grid .col-xs-offset-2{margin-left:16.66666667%}.au-grid .col-xs-offset-3{margin-left:25%}.au-grid .col-xs-offset-4{margin-left:33.33333333%}.au-grid .col-xs-offset-5{margin-left:41.66666667%}.au-grid .col-xs-offset-6{margin-left:50%}.au-grid .col-xs-offset-7{margin-left:58.33333333%}.au-grid .col-xs-offset-8{margin-left:66.66666667%}.au-grid .col-xs-offset-9{margin-left:75%}.au-grid .col-xs-offset-10{margin-left:83.33333333%}.au-grid .col-xs-offset-11{margin-left:91.66666667%}.au-grid .col-xs-offset-12{margin-left:100%}@media (min-width: 768px){.au-grid .col-sm-1,.au-grid .col-sm-2,.au-grid .col-sm-3,.au-grid .col-sm-4,.au-grid .col-sm-5,.au-grid .col-sm-6,.au-grid .col-sm-7,.au-grid .col-sm-8,.au-grid .col-sm-9,.au-grid .col-sm-10,.au-grid .col-sm-11,.au-grid .col-sm-12{float:left}.au-grid .col-sm-1{width:8.33333333%}.au-grid .col-sm-2{width:16.66666667%}.au-grid .col-sm-3{width:25%}.au-grid .col-sm-4{width:33.33333333%}.au-grid .col-sm-5{width:41.66666667%}.au-grid .col-sm-6{width:50%}.au-grid .col-sm-7{width:58.33333333%}.au-grid .col-sm-8{width:66.66666667%}.au-grid .col-sm-9{width:75%}.au-grid .col-sm-10{width:83.33333333%}.au-grid .col-sm-11{width:91.66666667%}.au-grid .col-sm-12{width:100%}.au-grid .col-sm-pull-0{right:auto}.au-grid .col-sm-pull-1{right:8.33333333%}.au-grid .col-sm-pull-2{right:16.66666667%}.au-grid .col-sm-pull-3{right:25%}.au-grid .col-sm-pull-4{right:33.33333333%}.au-grid .col-sm-pull-5{right:41.66666667%}.au-grid .col-sm-pull-6{right:50%}.au-grid .col-sm-pull-7{right:58.33333333%}.au-grid .col-sm-pull-8{right:66.66666667%}.au-grid .col-sm-pull-9{right:75%}.au-grid .col-sm-pull-10{right:83.33333333%}.au-grid .col-sm-pull-11{right:91.66666667%}.au-grid .col-sm-pull-12{right:100%}.au-grid .col-sm-push-0{left:auto}.au-grid .col-sm-push-1{left:8.33333333%}.au-grid .col-sm-push-2{left:16.66666667%}.au-grid .col-sm-push-3{left:25%}.au-grid .col-sm-push-4{left:33.33333333%}.au-grid .col-sm-push-5{left:41.66666667%}.au-grid .col-sm-push-6{left:50%}.au-grid .col-sm-push-7{left:58.33333333%}.au-grid .col-sm-push-8{left:66.66666667%}.au-grid .col-sm-push-9{left:75%}.au-grid .col-sm-push-10{left:83.33333333%}.au-grid .col-sm-push-11{left:91.66666667%}.au-grid .col-sm-push-12{left:100%}.au-grid .col-sm-offset-0{margin-left:0%}.au-grid .col-sm-offset-1{margin-left:8.33333333%}.au-grid .col-sm-offset-2{margin-left:16.66666667%}.au-grid .col-sm-offset-3{margin-left:25%}.au-grid .col-sm-offset-4{margin-left:33.33333333%}.au-grid .col-sm-offset-5{margin-left:41.66666667%}.au-grid .col-sm-offset-6{margin-left:50%}.au-grid .col-sm-offset-7{margin-left:58.33333333%}.au-grid .col-sm-offset-8{margin-left:66.66666667%}.au-grid .col-sm-offset-9{margin-left:75%}.au-grid .col-sm-offset-10{margin-left:83.33333333%}.au-grid .col-sm-offset-11{margin-left:91.66666667%}.au-grid .col-sm-offset-12{margin-left:100%}}@media (min-width: 992px){.au-grid .col-md-1,.au-grid .col-md-2,.au-grid .col-md-3,.au-grid .col-md-4,.au-grid .col-md-5,.au-grid .col-md-6,.au-grid .col-md-7,.au-grid .col-md-8,.au-grid .col-md-9,.au-grid .col-md-10,.au-grid .col-md-11,.au-grid .col-md-12{float:left}.au-grid .col-md-1{width:8.33333333%}.au-grid .col-md-2{width:16.66666667%}.au-grid .col-md-3{width:25%}.au-grid .col-md-4{width:33.33333333%}.au-grid .col-md-5{width:41.66666667%}.au-grid .col-md-6{width:50%}.au-grid .col-md-7{width:58.33333333%}.au-grid .col-md-8{width:66.66666667%}.au-grid .col-md-9{width:75%}.au-grid .col-md-10{width:83.33333333%}.au-grid .col-md-11{width:91.66666667%}.au-grid .col-md-12{width:100%}.au-grid .col-md-pull-0{right:auto}.au-grid .col-md-pull-1{right:8.33333333%}.au-grid .col-md-pull-2{right:16.66666667%}.au-grid .col-md-pull-3{right:25%}.au-grid .col-md-pull-4{right:33.33333333%}.au-grid .col-md-pull-5{right:41.66666667%}.au-grid .col-md-pull-6{right:50%}.au-grid .col-md-pull-7{right:58.33333333%}.au-grid .col-md-pull-8{right:66.66666667%}.au-grid .col-md-pull-9{right:75%}.au-grid .col-md-pull-10{right:83.33333333%}.au-grid .col-md-pull-11{right:91.66666667%}.au-grid .col-md-pull-12{right:100%}.au-grid .col-md-push-0{left:auto}.au-grid .col-md-push-1{left:8.33333333%}.au-grid .col-md-push-2{left:16.66666667%}.au-grid .col-md-push-3{left:25%}.au-grid .col-md-push-4{left:33.33333333%}.au-grid .col-md-push-5{left:41.66666667%}.au-grid .col-md-push-6{left:50%}.au-grid .col-md-push-7{left:58.33333333%}.au-grid .col-md-push-8{left:66.66666667%}.au-grid .col-md-push-9{left:75%}.au-grid .col-md-push-10{left:83.33333333%}.au-grid .col-md-push-11{left:91.66666667%}.au-grid .col-md-push-12{left:100%}.au-grid .col-md-offset-0{margin-left:0%}.au-grid .col-md-offset-1{margin-left:8.33333333%}.au-grid .col-md-offset-2{margin-left:16.66666667%}.au-grid .col-md-offset-3{margin-left:25%}.au-grid .col-md-offset-4{margin-left:33.33333333%}.au-grid .col-md-offset-5{margin-left:41.66666667%}.au-grid .col-md-offset-6{margin-left:50%}.au-grid .col-md-offset-7{margin-left:58.33333333%}.au-grid .col-md-offset-8{margin-left:66.66666667%}.au-grid .col-md-offset-9{margin-left:75%}.au-grid .col-md-offset-10{margin-left:83.33333333%}.au-grid .col-md-offset-11{margin-left:91.66666667%}.au-grid .col-md-offset-12{margin-left:100%}}@media (min-width: 1200px){.au-grid .col-lg-1,.au-grid .col-lg-2,.au-grid .col-lg-3,.au-grid .col-lg-4,.au-grid .col-lg-5,.au-grid .col-lg-6,.au-grid .col-lg-7,.au-grid .col-lg-8,.au-grid .col-lg-9,.au-grid .col-lg-10,.au-grid .col-lg-11,.au-grid .col-lg-12{float:left}.au-grid .col-lg-1{width:8.33333333%}.au-grid .col-lg-2{width:16.66666667%}.au-grid .col-lg-3{width:25%}.au-grid .col-lg-4{width:33.33333333%}.au-grid .col-lg-5{width:41.66666667%}.au-grid .col-lg-6{width:50%}.au-grid .col-lg-7{width:58.33333333%}.au-grid .col-lg-8{width:66.66666667%}.au-grid .col-lg-9{width:75%}.au-grid .col-lg-10{width:83.33333333%}.au-grid .col-lg-11{width:91.66666667%}.au-grid .col-lg-12{width:100%}.au-grid .col-lg-pull-0{right:auto}.au-grid .col-lg-pull-1{right:8.33333333%}.au-grid .col-lg-pull-2{right:16.66666667%}.au-grid .col-lg-pull-3{right:25%}.au-grid .col-lg-pull-4{right:33.33333333%}.au-grid .col-lg-pull-5{right:41.66666667%}.au-grid .col-lg-pull-6{right:50%}.au-grid .col-lg-pull-7{right:58.33333333%}.au-grid .col-lg-pull-8{right:66.66666667%}.au-grid .col-lg-pull-9{right:75%}.au-grid .col-lg-pull-10{right:83.33333333%}.au-grid .col-lg-pull-11{right:91.66666667%}.au-grid .col-lg-pull-12{right:100%}.au-grid .col-lg-push-0{left:auto}.au-grid .col-lg-push-1{left:8.33333333%}.au-grid .col-lg-push-2{left:16.66666667%}.au-grid .col-lg-push-3{left:25%}.au-grid .col-lg-push-4{left:33.33333333%}.au-grid .col-lg-push-5{left:41.66666667%}.au-grid .col-lg-push-6{left:50%}.au-grid .col-lg-push-7{left:58.33333333%}.au-grid .col-lg-push-8{left:66.66666667%}.au-grid .col-lg-push-9{left:75%}.au-grid .col-lg-push-10{left:83.33333333%}.au-grid .col-lg-push-11{left:91.66666667%}.au-grid .col-lg-push-12{left:100%}.au-grid .col-lg-offset-0{margin-left:0%}.au-grid .col-lg-offset-1{margin-left:8.33333333%}.au-grid .col-lg-offset-2{margin-left:16.66666667%}.au-grid .col-lg-offset-3{margin-left:25%}.au-grid .col-lg-offset-4{margin-left:33.33333333%}.au-grid .col-lg-offset-5{margin-left:41.66666667%}.au-grid .col-lg-offset-6{margin-left:50%}.au-grid .col-lg-offset-7{margin-left:58.33333333%}.au-grid .col-lg-offset-8{margin-left:66.66666667%}.au-grid .col-lg-offset-9{margin-left:75%}.au-grid .col-lg-offset-10{margin-left:83.33333333%}.au-grid .col-lg-offset-11{margin-left:91.66666667%}.au-grid .col-lg-offset-12{margin-left:100%}}/*! @gov.au/header v4.1.12 */@media print{.au-header{background:#fff !important}.au-header a img{border:0 !important}.au-header,.au-header__brand,.au-header__subline{color:#000 !important}.au-header__brand-image{display:none !important}}.au-header{font-size:16px;font-size:1rem;line-height:1.5;padding:24px 0;padding:1.5rem 0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";color:#313131;background:#fff}@media (min-width: 768px){.au-header{font-size:20px;font-size:1.25rem;line-height:1.6}}@media (min-width: 768px){.au-header{padding:48px 0;padding:3rem 0}}.au-header.au-header--alt{background-color:#f5f5f5}.au-header.au-header--dark{color:#fff;background-color:#135E70}.au-header.au-header--alt.au-header--dark{color:#fff;background-color:#0d414d}.au-header__heading{font-size:20px;font-size:1.25rem;line-height:1.6;font-weight:bold;margin:0;padding:0}@media (min-width: 768px){.au-header__heading{font-size:32px;font-size:2rem;line-height:1.5}}.au-header__subline{max-width:42em;color:#636363}.au-header--dark .au-header__subline{color:#b8cfd4}.au-header__brand{min-width:192px;min-width:12rem}.au-header__brand:before,.au-header__brand:after{content:" ";display:table}.au-header__brand:after{clear:both}.au-header__brand .au-header__brand-image{display:block;border-style:none;max-width:192px;max-width:12rem}.au-header__brand .au-header__brand-image+.au-header__text{margin-top:16px;margin-top:1rem}@media (min-width: 768px){.au-header__brand{min-width:256px;min-width:16rem}.au-header__brand .au-header__brand-image{float:left;max-width:256px;max-width:16rem;margin-right:-256px;margin-right:-16rem}.au-header__brand .au-header__brand-image+.au-header__text{padding-left:16px;padding-left:1rem;margin-left:272px;margin-left:17rem;margin-top:0;float:left;border-left:1px solid gray}.au-header--dark .au-header__brand .au-header__brand-image+.au-header__text{border-left-color:#89afb8}}a.au-header__brand{display:inline-block;color:#313131;text-decoration:none}a.au-header__brand:focus{outline:3px solid #9263DE;outline-offset:2px}a.au-header__brand::-moz-focus-inner{border:0}a.au-header__brand:hover .au-header__text{text-decoration:underline;-webkit-text-decoration-skip:ink;text-decoration-skip-ink:auto}.au-header--dark a.au-header__brand{color:#fff}.au-header--dark a.au-header__brand:focus{outline:3px solid #C390F9}.au-header--dark a.au-header__brand::-moz-focus-inner{border:0}.au-header.au-header--hero{padding:48px 0 56px 0;padding:3rem 0 3.5rem 0}.au-header.au-header--hero .au-header__brand .au-header__brand-image{float:none}.au-header.au-header--hero .au-header__brand-image+.au-header__text{margin-top:32px;margin-top:2rem;border:0;margin:0;padding:0}.au-header.au-header--hero .au-header__brand-image+.au-header__text .au-header__heading{margin-top:32px;margin-top:2rem}.au-header.au-header--hero .au-header__heading{font-size:20px;font-size:1.25rem;line-height:1.6}@media (min-width: 768px){.au-header.au-header--hero .au-header__heading{font-size:40px;font-size:2.5rem;line-height:1.5}}.au-header.au-header--hero .au-header__heading+.au-header__subline{margin-top:12px;margin-top:.75rem}/*! @gov.au/headings v2.0.11 */.au-display-xxxl,.au-display-xxl,.au-display-xl,.au-display-lg,.au-display-md,.au-display-sm,.au-display-xs,.au-body h1,.au-body h2,.au-body h3,.au-body h4,.au-body h5,.au-body h6{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";display:block;font-weight:bold;margin:0}.au-body .au-display-xxxl,.au-display-xxxl{font-size:48px;font-size:3rem;line-height:1.25}.au-body h1,.au-body .au-display-xxl,.au-display-xxl{font-size:40px;font-size:2.5rem;line-height:1.3}.au-body h2,.au-body .au-display-xl,.au-display-xl{font-size:32px;font-size:2rem;line-height:1.25}.au-body h3,.au-body .au-display-lg,.au-display-lg{font-size:24px;font-size:1.5rem;line-height:1.33333333}.au-body h4,.au-body .au-display-md,.au-display-md{font-size:20px;font-size:1.25rem;line-height:1.2}.au-body h5,.au-body .au-display-sm,.au-display-sm{font-size:16px;font-size:1rem;line-height:1.25}.au-body h6,.au-body .au-display-xs,.au-display-xs{font-size:14px;font-size:.875rem;line-height:1.14285714}*+.au-display-xxxl,*+.au-display-xxl,*+.au-display-xl,*+.au-display-lg,*+.au-display-md,*+.au-display-sm,*+.au-display-xs{margin-top:16px;margin-top:1rem}.au-body *+h1,.au-body *+.au-display-xxl{margin-top:48px;margin-top:3rem}.au-body *+h2,.au-body *+.au-display-xl{margin-top:48px;margin-top:3rem}.au-body h1+h2,.au-body h2+h3,.au-body .au-display-xxl+h2,.au-body .au-display-xl+h3,.au-body h1+.au-display-xl,.au-body h2+.au-display-lg,.au-body .au-display-xxl+.au-display-xl,.au-body .au-display-xl+.au-display-lg,.au-body *+h3,.au-body *+h4,.au-body *+h5,.au-body *+h6,.au-body *+.au-display-md,.au-body *+.au-display-sm,.au-body *+.au-display-xs{margin-top:24px;margin-top:1.5rem}/*! @gov.au/inpage-nav v3.0.6 */.au-inpage-nav-links{font-size:16px;font-size:1rem;line-height:1.5;padding-left:24px;padding-left:1.5rem;margin-bottom:48px;margin-bottom:3rem;border-left:4px solid #00698f}*+.au-inpage-nav-links{margin-top:48px;margin-top:3rem}.au-body .au-inpage-nav-links>ul,.au-body .au-inpage-nav-links>ol{margin-top:16px;margin-top:1rem;list-style-type:none;padding:0}.au-body .au-inpage-nav-links>ul li,.au-body .au-inpage-nav-links>ol li{margin:0}.au-body .au-inpage-nav-links>ul *+li,.au-body .au-inpage-nav-links>ol *+li{margin-top:8px;margin-top:.5rem;margin-left:0}.au-inpage-nav-links.au-inpage-nav-links--dark{border-color:#61daff}.au-inpage-nav-links__heading,.au-body .au-inpage-nav-links__heading{font-weight:bold;font-size:1em}.au-inpage-nav-section{position:relative;padding-right:128px;padding-right:8rem}.au-inpage-nav-section-link{font-size:14px;font-size:.875rem;line-height:1.14285714;top:4px;top:.25rem;position:absolute;right:0;font-weight:normal}/*! @gov.au/keyword-list v3.0.5 */.au-keyword-list{font-size:24px;font-size:1.5rem;line-height:1.5}.au-keyword-list:before,.au-keyword-list:after{content:"";display:table}.au-keyword-list:after{clear:both}*+.au-keyword-list{margin-top:16px;margin-top:1rem}.au-body .au-keyword-list>li{margin-top:16px;margin-top:1rem;float:left;clear:both;list-style:none;margin-left:0}.au-keyword-list>li{font-weight:bold}.au-keyword-list>li>a{display:block}.au-keyword-list__small{font-size:16px;font-size:1rem;line-height:1;display:block;font-weight:normal}.au-body .au-keyword-list__small{color:#313131}.au-keyword-list--dark .au-keyword-list__small{color:#fff}/*! @gov.au/main-nav v1.0.7 */@media print{.au-main-nav{background:transparent !important;border-bottom:none !important}.au-main-nav a{color:#000 !important}.au-main-nav a:hover{background:transparent !important}.au-main-nav .active a{text-decoration:underline;border-color:#fff !important;background-color:transparent !important}.au-main-nav .au-link-list>li{border-color:#000 !important}.au-main-nav .au-link-list>li:last-of-type{border-bottom:1px solid !important}}@media print and (min-width: 992px){.au-main-nav{border-bottom:8px solid #000 !important;border-bottom:.5rem solid #000 !important}.au-main-nav .au-link-list>li:last-of-type{border-bottom:none !important}}@media print{.au-main-nav__toggle{display:none !important}.au-main-nav__menu{background:transparent !important;position:static !important;display:block !important;width:auto !important}.au-main-nav__menu .au-main-nav__menu-inner{padding:0 !important}}.au-main-nav{font-size:16px;font-size:1rem;line-height:1.5;border-bottom:8px solid #00698f;border-bottom:.5rem solid #00698f;background-color:#fff;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";color:#313131}.au-main-nav a,.au-main-nav .au-main-nav__toggle{padding:16px;padding:1rem;font-size:14px;font-size:.875rem;line-height:1.42857143;color:#00698f;text-decoration:none}.au-main-nav a:focus,.au-main-nav .au-main-nav__toggle:focus{outline:3px solid #9263DE;outline-offset:2px}.au-main-nav a::-moz-focus-inner,.au-main-nav .au-main-nav__toggle::-moz-focus-inner{border:0}.au-main-nav a:hover,.au-main-nav .au-main-nav__toggle:hover{text-decoration:underline;-webkit-text-decoration-skip:ink;text-decoration-skip-ink:auto;color:#313131;background-color:#f5f5f5}.au-main-nav a{display:block}.au-main-nav .active a{font-weight:bold;color:#313131}.au-main-nav .active a:hover{border-color:#f5f5f5}.au-main-nav .au-link-list{margin:0;padding:0}.au-main-nav .au-link-list:before,.au-main-nav .au-link-list:after{content:" ";display:table}.au-main-nav .au-link-list:after{clear:both}.au-main-nav .au-link-list li{margin:0}.au-main-nav .au-link-list>li{border-top:1px solid gray}.au-main-nav.au-main-nav--alt{background-color:#ebebeb}.au-main-nav.au-main-nav--alt a:hover,.au-main-nav.au-main-nav--alt .au-main-nav__toggle:hover{background-color:#e0e0e0}.au-main-nav.au-main-nav--alt .active a{border-color:#ebebeb}.au-main-nav.au-main-nav--alt .active a:hover{border-color:#e0e0e0}.au-main-nav.au-main-nav--dark{background-color:#135E70;border-color:#61daff}.au-main-nav.au-main-nav--dark a,.au-main-nav.au-main-nav--dark .au-main-nav__toggle{color:#61daff}.au-main-nav.au-main-nav--dark a:focus,.au-main-nav.au-main-nav--dark .au-main-nav__toggle:focus{outline:3px solid #C390F9}.au-main-nav.au-main-nav--dark a::-moz-focus-inner,.au-main-nav.au-main-nav--dark .au-main-nav__toggle::-moz-focus-inner{border:0}.au-main-nav.au-main-nav--dark a:hover,.au-main-nav.au-main-nav--dark .au-main-nav__toggle:hover{color:#fff;background-color:#104f5f}.au-main-nav.au-main-nav--dark .active a{color:#fff;border-color:#135E70}.au-main-nav.au-main-nav--dark .active a:hover{border-color:#104f5f}.au-main-nav.au-main-nav--dark .au-link-list>li{border-color:#89afb8}.au-main-nav.au-main-nav--dark.au-main-nav--alt{background-color:#0d414d}.au-main-nav.au-main-nav--dark.au-main-nav--alt a:hover,.au-main-nav.au-main-nav--dark.au-main-nav--alt .au-main-nav__toggle:hover{background-color:#0a323c}.au-main-nav.au-main-nav--dark.au-main-nav--alt .active a{border-color:#0d414d}.au-main-nav.au-main-nav--dark.au-main-nav--alt .active a:hover{border-color:#0a323c}@media (min-width: 992px){.au-main-nav .au-link-list>li{display:block;float:left;border:none}.au-main-nav a,.au-main-nav .au-main-nav__toggle{font-size:16px;font-size:1rem;line-height:1.5;padding:16px;padding:1rem}.au-main-nav .active a{border-bottom:8px solid #fff;border-bottom:.5rem solid #fff;margin-bottom:-8px;margin-bottom:-.5rem;font-weight:normal}}.au-main-nav__toggle{padding:8px 16px 8px;padding:.5rem 1rem .5rem;font-size:14px;font-size:.875rem;line-height:1.14285714;border:0;-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:transparent;cursor:pointer;display:none}.au-main-nav__toggle:before{font-size:16px;font-size:1rem;line-height:1;margin-bottom:4px;margin-bottom:.25rem;display:block;text-align:center}.au-main-nav__toggle.au-main-nav__toggle--open:before{content:"☰"}.au-main-nav__toggle.au-main-nav__toggle--close:before{content:"✕"}.js .au-main-nav__toggle{display:inline-block}@media (min-width: 992px){.js .au-main-nav__toggle{display:none}}.js .au-main-nav__content.au-main-nav__content--open .au-main-nav__menu{left:0;display:block}.js .au-main-nav__content.au-main-nav__content--open .au-main-nav__overlay{opacity:0.8;left:0;display:block}@media (min-width: 992px){.js .au-main-nav__content.au-main-nav__content--open .au-main-nav__overlay{display:none}}.js .au-main-nav__menu{background-color:#fff;display:none;overflow:auto;position:fixed;top:0;bottom:0;left:-280px;width:280px;z-index:200}.js .au-main-nav__menu .au-main-nav__menu-inner{padding:16px;padding:1rem}.au-main-nav.au-main-nav--alt .au-main-nav__menu{background-color:#ebebeb}.au-main-nav.au-main-nav--dark .au-main-nav__menu{background-color:#135E70}.au-main-nav.au-main-nav--alt.au-main-nav--dark .au-main-nav__menu{background-color:#0d414d}@media (min-width: 992px){.js .au-main-nav__menu{position:static;display:block;width:auto;overflow:inherit;background-color:transparent}.js .au-main-nav__menu .au-main-nav__menu-inner{padding:0}}.au-main-nav__overlay{-webkit-transition:opacity 0.25s ease-out;transition:opacity 0.25s ease-out;background-color:#000;cursor:pointer;position:fixed;top:0;left:0;bottom:0;width:100%;z-index:190;opacity:0.4;display:none}.ie8 .au-main-nav__overlay{filter:alpha(opacity=80)}.js .au-main-nav__scroll--locked{overflow:hidden}@media (min-width: 992px){.js .au-main-nav__scroll--locked{overflow:visible}}/*! @gov.au/page-alerts v2.1.3 */@media print{.au-page-alerts{border-color:#000 !important;background-color:#fff !important;border-left:2px solid #000 !important;padding-top:3em !important}.au-page-alerts:after{background:none !important;content:'info' !important;top:1em !important;left:0 !important;font-size:12px !important;border-right:1px solid #000 !important;border-bottom:1px solid #000 !important;padding:0.5em !important;width:auto !important}.au-page-alerts--success:after{content:'success' !important}.au-page-alerts--warning:after{content:'warning' !important}.au-page-alerts--error:after{content:'error' !important}}.au-page-alerts{padding:16px;padding:1rem;font-size:16px;font-size:1rem;line-height:1.5;position:relative;border:solid 3px #00bfe9;border-left-width:48px;border-left-width:3rem;border-radius:4px;word-wrap:break-word}*+.au-page-alerts{margin-top:16px;margin-top:1rem}.au-page-alerts:before,.au-page-alerts:after{content:' ';position:absolute;top:50%;left:-36px;left:-2.25rem;width:24px;width:1.5rem;height:24px;height:1.5rem;margin-top:-12px;margin-top:-.75rem;border-left-width:-12px;border-left-width:-.75rem;display:block;background-repeat:no-repeat;background-color:#fff}.ie8 .au-page-alerts:before,.lt-ie8 .au-page-alerts:before,.ie8 .au-page-alerts:after,.lt-ie8 .au-page-alerts:after{background:none;text-align:center;background-color:#313131;color:#fff;font-weight:bold}.au-page-alerts:after{background-color:transparent;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23313131' d='M11 17.8h2v-8h-2v8zm0-11.6v2h2v-2h-2z'/%3E%3C/svg%3E")}.ie8 .au-page-alerts:after,.lt-ie8 .au-page-alerts:after{content:'i'}.au-page-alerts:before{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%2300bfe9' d='M0,0v24h24V0H0z M12,23C5.9,23,1,18.1,1,12C1,5.9,5.9,1,12,1s11,4.9,11,11C23,18.1,18.1,23,12,23z'/%3E%3C/svg%3E")}.au-page-alerts.au-page-alerts--alt:before{background-color:#f5f5f5}.au-page-alerts.au-page-alerts--dark:before{background-color:#135E70}.au-page-alerts.au-page-alerts--dark:after{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23fff' d='M11 17.8h2v-8h-2v8zm0-11.6v2h2v-2h-2z'/%3E%3C/svg%3E")}.au-page-alerts.au-page-alerts--alt.au-page-alerts--dark:before{background-color:#104f5f}.au-page-alerts--success{border-color:#0b996c}.au-page-alerts--success:before{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%230b996c' d='M0,0v24h24V0H0z M12,23C5.9,23,1,18.1,1,12C1,5.9,5.9,1,12,1s11,4.9,11,11C23,18.1,18.1,23,12,23z'/%3E%3C/svg%3E")}.au-page-alerts--success:after{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23313131' d='M10.4 16.9l-4.7-4.7 1.4-1.4 3.3 3.3 6.3-6.3 1.4 1.4z'/%3E%3C/svg%3E")}.ie8 .au-page-alerts--success:after,.lt-ie8 .au-page-alerts--success:after{content:'✓'}.au-page-alerts--success.au-page-alerts--dark:after{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23fff' d='M10.4 16.9l-4.7-4.7 1.4-1.4 3.3 3.3 6.3-6.3 1.4 1.4z'/%3E%3C/svg%3E")}.au-page-alerts--warning{border-color:#f69900}.au-page-alerts--warning:before{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23f69900' d='M0,24h24v-3.2H0V24z M12,0l12,20.8V0H12z M0,0v20.8L12,0H0z'/%3E%3C/svg%3E")}.au-page-alerts--warning:after{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23313131' d='M11 17h2v-2h-2v2zm0-8.6v5h2v-5h-2z'/%3E%3C/svg%3E")}.ie8 .au-page-alerts--warning:after,.lt-ie8 .au-page-alerts--warning:after{content:'!'}.au-page-alerts--warning.au-page-alerts--dark:after{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23fff' d='M11 17h2v-2h-2v2zm0-8.6v5h2v-5h-2z'/%3E%3C/svg%3E")}.au-page-alerts--error{border-color:#d60000}.au-page-alerts--error:before{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23d60000' d='M0,0v24h24V0H0z M22.9,16.6L16.5,23H7.4L1,16.5V7.4L7.4,1h9.2l6.3,6.4V16.6z'/%3E%3C/svg%3E")}.au-page-alerts--error:after{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23313131' d='M17 8.4L15.6 7 12 10.6 8.4 7 7 8.4l3.6 3.6L7 15.6 8.4 17l3.6-3.6 3.6 3.6 1.4-1.4-3.6-3.6z'/%3E%3C/svg%3E")}.ie8 .au-page-alerts--error:after,.lt-ie8 .au-page-alerts--error:after{content:'!'}.au-page-alerts--error.au-page-alerts--dark:after{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23fff' d='M17 8.4L15.6 7 12 10.6 8.4 7 7 8.4l3.6 3.6L7 15.6 8.4 17l3.6-3.6 3.6 3.6 1.4-1.4-3.6-3.6z'/%3E%3C/svg%3E")}.au-page-alerts__sronly{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}/*! @gov.au/progress-indicator v3.1.7 */@media print{.au-progress-indicator{border-top-color:#000 !important}.au-body .au-progress-indicator__link,.au-progress-indicator__link{color:#000 !important;border-bottom-color:#000 !important;border-left-color:transparent !important;padding-left:6px !important}.au-body .au-progress-indicator__link.au-progress-indicator__link--doing,.au-progress-indicator__link.au-progress-indicator__link--doing{border-left-color:#000 !important}.au-body .au-progress-indicator__link:after,.au-progress-indicator__link:after{display:none}.au-progress-indicator__status{color:#000 !important}}.au-body .au-progress-indicator,.au-progress-indicator{font-size:16px;font-size:1rem;line-height:1.25;margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";list-style:none;padding:0;border-top:1px solid gray}.au-body .au-progress-indicator>li,.au-progress-indicator>li{margin:0}.au-body .au-progress-indicator.au-progress-indicator--dark,.au-progress-indicator.au-progress-indicator--dark{border-color:#89afb8}*+.au-progress-indicator,.au-body *+.au-progress-indicator{margin-top:16px;margin-top:1rem}.au-body .au-progress-indicator__link,.au-progress-indicator__link{font-size:16px;font-size:1rem;line-height:1.25;padding:12px 12px 12px 44px;padding:.75rem .75rem .75rem 2.75rem;position:relative;display:block;color:#313131;text-decoration:none;-webkit-appearance:none;-moz-appearance:none;appearance:none;background:transparent;-webkit-box-sizing:border-box;box-sizing:border-box;width:100%;text-align:left;border:none;border-bottom:1px solid gray;border-left:3px solid transparent;-webkit-transition:background-color 0.1s ease-in-out;transition:background-color 0.1s ease-in-out;cursor:pointer}.au-body .au-progress-indicator__link:hover,.au-progress-indicator__link:hover{background-color:#f5f5f5}.au-body .au-progress-indicator__link:focus,.au-progress-indicator__link:focus{outline:3px solid #9263DE;outline-offset:2px}.au-body .au-progress-indicator__link::-moz-focus-inner,.au-progress-indicator__link::-moz-focus-inner{border:0}.au-body .au-progress-indicator__link:after,.au-progress-indicator__link:after{left:8px;left:.5rem;width:24px;width:1.5rem;content:'';position:absolute;top:0;bottom:0;background-image:url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='%23636363' d='M12 0C5.4 0 0 5.4 0 12s5.4 12 12 12 12-5.4 12-12S18.6 0 12 0zm0 22C6.5 22 2 17.5 2 12S6.5 2 12 2s10 4.5 10 10-4.5 10-10 10z'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:0 center}.ie8 .au-body .au-progress-indicator__link:after,.lt-ie8 .au-body .au-progress-indicator__link:after,.ie8 .au-progress-indicator__link:after,.lt-ie8 .au-progress-indicator__link:after{top:6px;content:'-'}.au-body .au-progress-indicator__link.au-progress-indicator__link--doing,.au-progress-indicator__link.au-progress-indicator__link--doing{border-left-color:#00698f;font-weight:bold}.au-body .au-progress-indicator__link.au-progress-indicator__link--doing:after,.au-progress-indicator__link.au-progress-indicator__link--doing:after{background-image:url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='%2300698f' d='M12 0C5.4 0 0 5.4 0 12s5.4 12 12 12 12-5.4 12-12S18.6 0 12 0zm0 22C6.5 22 2 17.5 2 12S6.5 2 12 2s10 4.5 10 10-4.5 10-10 10z'/%3E%3Ccircle fill='%2300698f' cx='6.5' cy='12' r='1.5'%3E%3C/circle%3E%3Ccircle fill='%2300698f' cx='12' cy='12' r='1.5'%3E%3C/circle%3E%3Ccircle fill='%2300698f' cx='17.5' cy='12' r='1.5'%3E%3C/circle%3E%3C/svg%3E")}.ie8 .au-body .au-progress-indicator__link.au-progress-indicator__link--doing:after,.lt-ie8 .au-body .au-progress-indicator__link.au-progress-indicator__link--doing:after,.ie8 .au-progress-indicator__link.au-progress-indicator__link--doing:after,.lt-ie8 .au-progress-indicator__link.au-progress-indicator__link--doing:after{content:'...'}.au-body .au-progress-indicator__link.au-progress-indicator__link--done:after,.au-progress-indicator__link.au-progress-indicator__link--done:after{background-image:url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='%2300698f' d='M12 0C5.4 0 0 5.4 0 12s5.4 12 12 12 12-5.4 12-12S18.6 0 12 0zm0 22C6.5 22 2 17.5 2 12S6.5 2 12 2s10 4.5 10 10-4.5 10-10 10z'/%3E%3Cpath fill='%2300698f' d='M18.744186,9.23753281 C18.744186,9.48293963 18.6627907,9.71391076 18.5,9.88713911 L11.3895349,17.7257218 C11.2267442,17.8989501 10.996124,18 10.7655039,18 C10.5484496,18 10.3178295,17.8989501 10.1550388,17.7257218 L5.24418605,12.5 C5.08139535,12.3267717 5,12.0958005 5,11.8503937 C5,11.6049869 5.08139535,11.3595801 5.24418605,11.1863517 L6.47868217,9.88713911 C6.64147287,9.71391076 6.85852713,9.61286089 7.08914729,9.61286089 C7.31976744,9.61286089 7.53682171,9.71391076 7.6996124,9.88713911 L10.7655039,13.1496063 L16.0445736,7.27427822 C16.2073643,7.10104987 16.4244186,7 16.6550388,7 C16.8856589,7 17.1027132,7.10104987 17.2655039,7.27427822 L18.5,8.57349081 C18.6627907,8.74671916 18.744186,8.99212598 18.744186,9.23753281 Z'/%3E%3C/svg%3E")}.ie8 .au-body .au-progress-indicator__link.au-progress-indicator__link--done:after,.lt-ie8 .au-body .au-progress-indicator__link.au-progress-indicator__link--done:after,.ie8 .au-progress-indicator__link.au-progress-indicator__link--done:after,.lt-ie8 .au-progress-indicator__link.au-progress-indicator__link--done:after{content:'✓'}.au-body--dark .au-progress-indicator--dark .au-body .au-progress-indicator__link,.au-progress-indicator--dark .au-body .au-progress-indicator__link,.au-body--dark .au-progress-indicator--dark .au-progress-indicator__link,.au-progress-indicator--dark .au-progress-indicator__link{color:#fff;border-bottom-color:#89afb8}.au-body--dark .au-progress-indicator--dark .au-body .au-progress-indicator__link:focus,.au-progress-indicator--dark .au-body .au-progress-indicator__link:focus,.au-body--dark .au-progress-indicator--dark .au-progress-indicator__link:focus,.au-progress-indicator--dark .au-progress-indicator__link:focus{outline:3px solid #C390F9}.au-body--dark .au-progress-indicator--dark .au-body .au-progress-indicator__link::-moz-focus-inner,.au-progress-indicator--dark .au-body .au-progress-indicator__link::-moz-focus-inner,.au-body--dark .au-progress-indicator--dark .au-progress-indicator__link::-moz-focus-inner,.au-progress-indicator--dark .au-progress-indicator__link::-moz-focus-inner{border:0}.au-body--dark .au-progress-indicator--dark .au-body .au-progress-indicator__link:hover,.au-progress-indicator--dark .au-body .au-progress-indicator__link:hover,.au-body--dark .au-progress-indicator--dark .au-progress-indicator__link:hover,.au-progress-indicator--dark .au-progress-indicator__link:hover{background-color:#104f5f}.au-body--dark .au-progress-indicator--dark .au-body .au-progress-indicator__link:after,.au-progress-indicator--dark .au-body .au-progress-indicator__link:after,.au-body--dark .au-progress-indicator--dark .au-progress-indicator__link:after,.au-progress-indicator--dark .au-progress-indicator__link:after{background-image:url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='%23b8cfd4' d='M12 0C5.4 0 0 5.4 0 12s5.4 12 12 12 12-5.4 12-12S18.6 0 12 0zm0 22C6.5 22 2 17.5 2 12S6.5 2 12 2s10 4.5 10 10-4.5 10-10 10z'/%3E%3C/svg%3E")}.au-body--dark .au-progress-indicator--dark .au-body .au-progress-indicator__link.au-progress-indicator__link--done:after,.au-progress-indicator--dark .au-body .au-progress-indicator__link.au-progress-indicator__link--done:after,.au-body--dark .au-progress-indicator--dark .au-progress-indicator__link.au-progress-indicator__link--done:after,.au-progress-indicator--dark .au-progress-indicator__link.au-progress-indicator__link--done:after{background-image:url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='%2361daff' d='M12 0C5.4 0 0 5.4 0 12s5.4 12 12 12 12-5.4 12-12S18.6 0 12 0zm0 22C6.5 22 2 17.5 2 12S6.5 2 12 2s10 4.5 10 10-4.5 10-10 10z'/%3E%3Cpath fill='%2361daff' d='M18.744186,9.23753281 C18.744186,9.48293963 18.6627907,9.71391076 18.5,9.88713911 L11.3895349,17.7257218 C11.2267442,17.8989501 10.996124,18 10.7655039,18 C10.5484496,18 10.3178295,17.8989501 10.1550388,17.7257218 L5.24418605,12.5 C5.08139535,12.3267717 5,12.0958005 5,11.8503937 C5,11.6049869 5.08139535,11.3595801 5.24418605,11.1863517 L6.47868217,9.88713911 C6.64147287,9.71391076 6.85852713,9.61286089 7.08914729,9.61286089 C7.31976744,9.61286089 7.53682171,9.71391076 7.6996124,9.88713911 L10.7655039,13.1496063 L16.0445736,7.27427822 C16.2073643,7.10104987 16.4244186,7 16.6550388,7 C16.8856589,7 17.1027132,7.10104987 17.2655039,7.27427822 L18.5,8.57349081 C18.6627907,8.74671916 18.744186,8.99212598 18.744186,9.23753281 Z'/%3E%3C/svg%3E")}.au-body--dark .au-progress-indicator--dark .au-body .au-progress-indicator__link.au-progress-indicator__link--doing,.au-progress-indicator--dark .au-body .au-progress-indicator__link.au-progress-indicator__link--doing,.au-body--dark .au-progress-indicator--dark .au-progress-indicator__link.au-progress-indicator__link--doing,.au-progress-indicator--dark .au-progress-indicator__link.au-progress-indicator__link--doing{border-left-color:#61daff}.au-body--dark .au-progress-indicator--dark .au-body .au-progress-indicator__link.au-progress-indicator__link--doing:after,.au-progress-indicator--dark .au-body .au-progress-indicator__link.au-progress-indicator__link--doing:after,.au-body--dark .au-progress-indicator--dark .au-progress-indicator__link.au-progress-indicator__link--doing:after,.au-progress-indicator--dark .au-progress-indicator__link.au-progress-indicator__link--doing:after{background-image:url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='%2361daff' d='M12 0C5.4 0 0 5.4 0 12s5.4 12 12 12 12-5.4 12-12S18.6 0 12 0zm0 22C6.5 22 2 17.5 2 12S6.5 2 12 2s10 4.5 10 10-4.5 10-10 10z'/%3E%3Ccircle fill='%2361daff' cx='6.5' cy='12' r='1.5'%3E%3C/circle%3E%3Ccircle fill='%2361daff' cx='12' cy='12' r='1.5'%3E%3C/circle%3E%3Ccircle fill='%2361daff' cx='17.5' cy='12' r='1.5'%3E%3C/circle%3E%3C/svg%3E")}.au-progress-indicator__status{font-size:14px;font-size:.875rem;line-height:1.14285714;display:block;font-weight:normal;color:#636363}.au-progress-indicator--dark .au-progress-indicator__status{color:#b8cfd4}/*! @gov.au/responsive-media v2.0.14 */.au-responsive-media-vid{position:relative;display:block;height:0;padding:0;overflow:hidden}.au-responsive-media-vid>.au-responsive-media-vid__item{position:absolute;top:0;left:0;height:100%;width:100%;border:0}.au-responsive-media-vid.au-responsive-media-vid--16x9{padding-bottom:56.25%}.au-responsive-media-vid.au-responsive-media-vid--4x3{padding-bottom:75%}*+.au-responsive-media-vid{margin-top:16px;margin-top:1rem}.au-responsive-media-img,.au-body img,.au-responsive-media img{max-width:100%;height:auto}*+.au-responsive-media-img,.au-body *+img,.au-responsive-media *+img{margin-top:16px;margin-top:1rem}/*! @gov.au/select v2.0.11 */@media print{.au-select{border-color:#000 !important;background-image:url("data:image/svg+xml,%3Csvg fill='%23000' width='1.5em' height='auto' viewBox='0 0 28 12' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M1.9 1.1L8 7.2l6.1-6.1L16 2.9l-8 8-8-8 1.9-1.8z'/%3E%3Cpath fill='none' d='M2-5.8h24v24H2v-24z'/%3E%3C/svg%3E") !important}}.au-select{font-size:16px;font-size:1rem;line-height:1.5;padding:8px 36px 8px 12px;padding:.5rem 2.25rem .5rem .75rem;height:46px;height:2.875rem;position:relative;vertical-align:middle;display:inline-block;-webkit-appearance:none;-moz-appearance:none;appearance:none;border:3px solid gray;text-indent:0.01px;text-overflow:'';background-color:#fff;-webkit-box-sizing:border-box;box-sizing:border-box;border-radius:4px;cursor:pointer;background-image:url("data:image/svg+xml,%3Csvg fill='%2300698f' width='1.5em' height='auto' viewBox='0 0 28 12' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M1.9 1.1L8 7.2l6.1-6.1L16 2.9l-8 8-8-8 1.9-1.8z'/%3E%3Cpath fill='none' d='M2-5.8h24v24H2v-24z'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right center;background-size:1.5em auto;vertical-align:middle}.au-select:focus{outline:3px solid #9263DE;outline-offset:2px}.au-select::-moz-focus-inner{border:0}.au-select:focus{border-radius:0}.au-select[disabled]{cursor:not-allowed;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=30)";opacity:0.3}.au-select:disabled{cursor:not-allowed;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=30)";opacity:0.3}.au-select.au-select--dark:invalid,.au-select:invalid{background-color:#fdf2f2;border-color:#d60000}.au-select.au-select--dark.au-select--invalid,.au-select.au-select--invalid{background-color:#fdf2f2;border-color:#d60000}.au-select.au-select--dark.au-select--valid,.au-select.au-select--valid{background-color:#f3faf8;border-color:#0b996c}.ie8 .au-select:after,.ie9 .au-select:after{display:none}.au-select::-ms-expand{display:none}.ie8 .au-select,.ie9 .au-select{padding-right:4px;padding-right:.25rem}.au-select.au-select--dark{border-color:#fff}.au-select.au-select--dark:focus{outline:3px solid #C390F9}.au-select.au-select--dark::-moz-focus-inner{border:0}.au-select.au-select--block{width:100%}.au-select:-moz-focusring{color:transparent;text-shadow:0 0 0 #000}html>body .au-select,x:-moz-any-link,x:default{padding-right:16px;padding-right:1rem}@supports (-moz-osx-font-smoothing: auto){html body .au-select{padding-right:36px;padding-right:2.25rem}}/*! @gov.au/side-nav v5.0.7 */@media print{.au-side-nav{background:transparent !important}.au-side-nav a{color:#000 !important;text-decoration:underline !important}.au-side-nav a:hover{background:transparent !important}.au-side-nav .au-accordion__title{display:none}.au-side-nav__content ul ul ul a:before{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='%23000' d='M2 10h12v1H2zM2 5h1v5H2z'/%3E%3C/svg%3E") !important}.au-side-nav__content>ul>li{border-color:#000 !important}}.au-side-nav{font-size:16px;font-size:1rem;line-height:1.5;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";background-color:#ebebeb;border-radius:4px;overflow:hidden;border:0}.au-side-nav a,.au-side-nav .active>span{padding:16px;padding:1rem;font-size:14px;font-size:.875rem;line-height:1.42857143;color:#636363;display:block}.au-side-nav a{text-decoration:none}.au-side-nav a:hover{text-decoration:underline;-webkit-text-decoration-skip:ink;text-decoration-skip-ink:auto;background-color:#e0e0e0}.au-side-nav a:focus{outline:3px solid #9263DE;outline-offset:2px}.au-side-nav a::-moz-focus-inner{border:0}.au-side-nav .au-link-list{padding:0;margin:0}.au-side-nav .au-link-list li{margin:0}.au-side-nav .au-accordion__body{overflow:visible}.au-side-nav .au-accordion__title{font-size:16px;font-size:1rem;line-height:1.5;color:#00698f;font-weight:normal;text-decoration:underline;-webkit-text-decoration-skip:ink;text-decoration-skip-ink:auto;background-color:inherit}.au-side-nav .au-accordion__title:hover{text-decoration:none}.au-side-nav .au-accordion__title:focus{outline-offset:-3px}.no-js .au-side-nav .au-accordion__title{display:none}.au-side-nav .au-accordion__body-wrapper{border:0;padding:0}@media (min-width: 768px){.au-side-nav{background:transparent;border-radius:0;overflow:visible}.au-side-nav .au-accordion__body.au-accordion--closed{display:block;height:auto}.au-side-nav a:hover{background-color:#f5f5f5}.au-side-nav .au-accordion__title{display:none}}.au-side-nav__content{margin:0 16px;margin:0 1rem}.au-side-nav__content ul ul a{padding-left:32px;padding-left:2rem}.au-side-nav__content ul ul ul a{padding-left:60px;padding-left:3.75rem}.au-side-nav__content ul ul ul ul a{padding-left:80px;padding-left:5rem}.au-side-nav__content ul ul .active>span{padding-left:32px;padding-left:2rem}.au-side-nav__content ul ul ul .active>span{padding-left:60px;padding-left:3.75rem}.au-side-nav__content ul ul ul ul .active>span{padding-left:80px;padding-left:5rem}.au-side-nav__content .active>span{font-weight:bold;color:#313131}.au-side-nav__content ul ul ul a:before,.au-side-nav__content ul ul ul .active>span:before{content:" ";width:16px;width:1rem;height:16px;height:1rem;background-size:16px;background-size:1rem;margin-left:-24px;margin-left:-1.5rem;display:block;float:left;background-repeat:no-repeat;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='gray' d='M2 10h12v1H2zM2 5h1v5H2z'/%3E%3C/svg%3E")}.au-side-nav__content>ul>li{border-bottom:1px solid gray}.au-side-nav__content>ul>li:last-of-type{border:none}@media (min-width: 768px){.au-side-nav__content{margin:0}}.au-sidenav__title{margin:0}.au-sidenav__title a{font-size:16px;font-size:1rem;line-height:1.5;color:#313131;border-bottom:2px solid gray}.au-side-nav.au-side-nav--alt{background:#fff}.au-side-nav.au-side-nav--alt a:hover{background:#f5f5f5}@media (min-width: 768px){.au-side-nav.au-side-nav--alt{background:transparent}.au-side-nav.au-side-nav--alt a:hover{background-color:#e0e0e0}}.au-side-nav.au-side-nav--dark{background:#0d414d}.au-side-nav.au-side-nav--dark .au-accordion__title{color:#61daff;background-color:inherit}.au-side-nav.au-side-nav--dark a{color:#b8cfd4}.au-side-nav.au-side-nav--dark a:hover{background:#0a323c}.au-side-nav.au-side-nav--dark a:focus{outline:3px solid #C390F9}.au-side-nav.au-side-nav--dark a::-moz-focus-inner{border:0}.au-side-nav.au-side-nav--dark .au-side-nav__content .active>span{color:#fff}.au-side-nav.au-side-nav--dark .au-side-nav__content ul ul ul a:before,.au-side-nav.au-side-nav--dark .au-side-nav__content ul ul ul .active>span:before{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='%2389afb8' d='M2 10h12v1H2zM2 5h1v5H2z'/%3E%3C/svg%3E")}.au-side-nav.au-side-nav--dark .au-side-nav__content>ul>li{border-color:#89afb8}.au-side-nav.au-side-nav--dark .au-sidenav__title a{border-color:#89afb8;color:#fff}@media (min-width: 768px){.au-side-nav.au-side-nav--dark{background:transparent}.au-side-nav.au-side-nav--dark a:hover{background-color:#104f5f}}.au-side-nav.au-side-nav--dark.au-side-nav--alt{background:#135E70}.au-side-nav.au-side-nav--dark.au-side-nav--alt a:hover{background:#104f5f}@media (min-width: 768px){.au-side-nav.au-side-nav--dark.au-side-nav--alt{background:transparent}.au-side-nav.au-side-nav--dark.au-side-nav--alt a:hover{background-color:#0a323c}}/*! @gov.au/skip-link v2.0.16 */@media print{.au-skip-link__link{background:#fff !important}}.au-skip-link{font-size:20px;font-size:1.25rem;line-height:1;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";color:#313131}.au-skip-link__link{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.au-skip-link__link:active,.au-skip-link__link:focus{outline:3px solid #9263DE;outline-offset:2px;top:16px;top:1rem;left:16px;left:1rem;padding:24px;padding:1.5rem;clip:auto;height:auto;margin:0;overflow:visible;position:absolute;width:auto;color:#fff;background-color:#00698f;text-decoration:underline;-webkit-text-decoration-skip:ink;text-decoration-skip-ink:auto;z-index:600}.au-body .au-skip-link__link:hover,.au-skip-link__link:hover{text-decoration:none;color:#fff}/*! @gov.au/table v0.1.3 */.au-table{font-size:16px;font-size:1rem;line-height:1.5;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";width:100%;border-collapse:collapse;border-spacing:0}.au-table .au-table__caption{font-size:20px;font-size:1.25rem;line-height:1.6;font-weight:bold;text-align:left;display:table-caption;padding-bottom:8px;padding-bottom:.5rem}.au-table .au-table__head{display:table-header-group;border-bottom:4px solid #BBB;border-bottom:.25rem solid #BBB}.au-table .au-table__head .au-table__header{text-align:left;padding:12px;padding:.75rem}.au-table .au-table__head .au-table__header.au-table__header--width-10{width:10%}.au-table .au-table__head .au-table__header.au-table__header--width-20{width:20%}.au-table .au-table__head .au-table__header.au-table__header--width-25{width:25%}.au-table .au-table__head .au-table__header.au-table__header--width-33{width:33%}.au-table .au-table__head .au-table__header.au-table__header--width-50{width:50%}.au-table .au-table__head .au-table__header.au-table__header--width-75{width:75%}.au-table .au-table__head .au-table__header.au-table__header--numeric{text-align:right}.au-table .au-table__head .au-table__header:focus{outline:3px solid #9263DE}.au-table .au-table__row{display:table-row}.au-table .au-table__body{display:table-row-group}.au-table .au-table__body .au-table__cell{padding:12px;padding:.75rem;text-align:left;border-bottom:1px solid silver}.au-table .au-table__body .au-table__cell.au-table__cell--numeric{text-align:right;font-variant:tabular-nums}.au-table .au-table__body .au-table__cell:focus{outline:3px solid #9263DE}.au-table.au-table--striped .au-table__body .au-table__row:nth-last-child(odd){background-color:#F2F2F2}.au-table__wrapper{overflow-x:auto}/*! @gov.au/tags v3.1.7 */@media print{.au-tags{color:#000 !important}.au-tags__item{border-color:#000 !important}.au-tags__item a{color:#000 !important}}.au-tags{font-size:16px;font-size:1rem;line-height:1.5;display:block;margin:0;padding:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";color:#313131}.au-tags.au-tags--dark{color:#fff}.au-tags>li{margin:8px 4px 0 0;margin:.5rem .25rem 0 0;padding:0 8px;padding:0 .5rem;border:1px solid #00698f;border-radius:4px;display:inline-block}.au-tags>li>a,.au-tags>li>button{margin:0 -8px;margin:0 -.5rem;padding:0 8px;padding:0 .5rem;color:#00698f;display:inline-block;border-radius:4px}.au-tags>li>a:hover,.au-tags>li>button:hover{color:#313131;text-decoration:none;background-color:#f5f5f5}.au-tags>li>a:focus,.au-tags>li>button:focus{outline:3px solid #9263DE;outline-offset:2px}.au-tags>li>a::-moz-focus-inner,.au-tags>li>button::-moz-focus-inner{border:0}.au-tags>li>a:focus,.au-tags>li>button:focus{outline-offset:-1px}.au-tags.au-tags--dark>li{border-color:#61daff}.au-tags.au-tags--dark>li>a,.au-tags.au-tags--dark>li>button{color:#61daff}.au-tags.au-tags--dark>li>a:hover,.au-tags.au-tags--dark>li>button:hover{color:#fff;background-color:#104f5f}.au-tags.au-tags--dark>li>a:focus,.au-tags.au-tags--dark>li>button:focus{outline:3px solid #C390F9}.au-tags.au-tags--dark>li>a::-moz-focus-inner,.au-tags.au-tags--dark>li>button::-moz-focus-inner{border:0}/*! @gov.au/text-inputs v2.1.1 */@media print{.au-text-input{border-color:#000 !important}.au-text-input[disabled]{color:#636363 !important;background-color:#ccc !important;border:2px solid #ccc !important}.au-text-input:disabled{color:#636363 !important;background-color:#ccc !important;border:2px solid #ccc !important}}.au-text-input{-webkit-box-sizing:border-box;box-sizing:border-box;font-size:16px;font-size:1rem;line-height:1;padding:8px 16px;padding:.5rem 1rem;height:46px;height:2.875rem;border:3px solid gray;background-color:#fff;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";color:#313131;border-radius:4px;vertical-align:middle;-webkit-appearance:none;-moz-appearance:none;appearance:none;width:100%;max-width:205px;max-width:12.8125rem}.au-text-input.au-text-input--dark:invalid,.au-text-input:invalid{background-color:#fdf2f2;border-color:#d60000}.au-text-input.au-text-input--dark.au-text-input--invalid,.au-text-input.au-text-input--invalid{background-color:#fdf2f2;border-color:#d60000}.au-text-input.au-text-input--dark.au-text-input--valid,.au-text-input.au-text-input--valid{background-color:#f3faf8;border-color:#0b996c}.au-text-input[disabled]{cursor:not-allowed;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=30)";opacity:0.3}.au-text-input:disabled{cursor:not-allowed;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=30)";opacity:0.3}.au-text-input:focus{outline:3px solid #9263DE;outline-offset:2px}.au-text-input::-moz-focus-inner{border:0}.au-text-input:focus{border-radius:0;background-color:#fff}.au-text-input.au-text-input--dark{border-color:#fff}.au-text-input.au-text-input--dark[disabled]{-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=30)";opacity:0.3}.au-text-input.au-text-input--dark:disabled{-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=30)";opacity:0.3}.au-text-input.au-text-input--dark:focus{outline:3px solid #C390F9}.au-text-input.au-text-input--dark::-moz-focus-inner{border:0}.au-text-input.au-text-input--width-xs{max-width:69px;max-width:4.3rem}.au-text-input.au-text-input--width-sm{max-width:101px;max-width:6.3rem}.au-text-input.au-text-input--width-md{max-width:160px;max-width:10rem}.au-text-input.au-text-input--width-lg{max-width:288px;max-width:18rem}.au-text-input.au-text-input--width-xl{max-width:384px;max-width:24rem}.au-text-input.au-text-input--block{display:block;max-width:100%;-webkit-box-sizing:border-box;box-sizing:border-box}.au-text-input.au-text-input--number{font-family:"SFMono-Regular",Consolas,"Liberation Mono",Menlo,Courier,monospace;letter-spacing:2px}textarea.au-text-input{font-size:16px;font-size:1rem;line-height:1.5;height:auto;min-height:6em} +body { + border: 2rem red; +} + +.navbar-default{ + background-color: #313131; + border-color: #45c2f0; +} + +.au-header.au-header--dark{ + color:#fff; + background-color:#313131; +} + +.au-footer.au-footer--dark{ + color:#fff; + background-color:#313131; +} diff --git a/html/observatory/css/style.css b/html/observatory/css/style.css new file mode 100644 index 0000000..66a05f0 --- /dev/null +++ b/html/observatory/css/style.css @@ -0,0 +1,465 @@ + +html,body { + width: 100%; + height: 100%; + margin: 0px; + padding: 0px; +} +main.au-body { + background: #eee !important; + padding: 0 20px 0 20px; +} +.explanation { + margin-top: 2rem; + margin-bottom: 2rem; +} +.sigma-parent { + position: relative; + height: 100%; + min-height: 800px !important; + background: white; +} + +.sigma-expand { + position: absolute; + width: 100%; + height: 100%; + top: 0; + left: 0; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +canvas#sigma_bg_1 { + display: none; +} + +#attributepane { + display: none; + height:auto; + + background-color: #fff; + margin: 0; + word-wrap: break-word; + background-color:rgba(255,255,255,0.8); + padding: 0px 18px 0px 18px; + z-index: 1; + width: 80%; +} + + +#attributepane .text { + height:83%; +} + +#attributepane .headertext { + color: #000; + margin-bottom: 5px; + height: 14px; + border-bottom: 1px solid #999; + padding: 0px 0 10px 0; + font-size:16px; + font-weight:bold; +} + + +#attributepane .returntext em { + background-image: url('../images/sprite.png'); + background-repeat: no-repeat; + display: block; + width: 20px; + height: 20px; + background-position: -91px -13px; + float: left; +} + +#attributepane .returntext span { + padding-left: 5px; + display: block; +} + +#attributepane .close { + padding-left: 14px; + margin-top: 10px; +} + +#attributepane .close .c { + border-top: 2px solid #999; + padding: 10px 0 14px 0; +} + +#attributepane .close em { +background-image: url('../images/sprite.png'); +background-repeat: no-repeat; +background-position: -11px -13px; +display: block; +width: 24px; +height: 16px; +float: left; +} + +#attributepane .close span { +display: block; +width: 151px; +float: left; +} + +#attributepane .nodeattributes { + display:block; + max-width: 13em; + max-height: 400px; + overflow-y: scroll; + overflow-x: hidden; + border-bottom:1px solid #999; +} + +#attributepane .name { +font-size: 14px; +cursor: default; +padding-bottom: 10px; +padding-top: 18px; +font-weight:bold; +} + +#attributepane .data { + +} + +#attributepane .data .plus { +background-repeat: no-repeat; +background-image: url('../images/sprite.png'); +background-position: -171px -122px; +width: 22px; +height: 20px; +float: left; +display: block; +} + +#attributepane .link { +padding: 0 0 0 4px; +} + +#attributepane .link li { +padding-top: 2px; +cursor:pointer; +} + +#attributepane .p { +padding-top: 10px; +font-weight: bold; +font-size:14px; +} + +.left-close { +background-image: url('../images/fancybox_sprite.png'); +float: right; +z-index:99999; +cursor: pointer; +padding-left:31px; +line-height:36px; +background-repeat: no-repeat; +font-weight: bold; +font-size:14px; + +} + +#developercontainer { + margin-left:25px; + margin-bottom:25px; + position:fixed; + bottom:0; +} + + + + + + +#search { + padding: 20px 0 0px 2px; +} + +#search input[name=search] { +border: 1px solid #999; +background-color: #fff; +padding: 5px 7px 4px 7px; +width: 205px; +color: #000; +} + +#search input.empty { +color: #000; +} + +#search .state { +width: 14px; +height: 14px; +background-image: url('../images/sprite.png'); +float: right; +margin-top: 6px; +cursor: pointer; +background-position: -131px -13px; +} + +#search .state.searching { +background-position: -11px -13px; +} + +#search .results { + display: none; +/* border: 1px solid #999;*/ + margin: 6px; + height: 150px; + overflow-y: scroll; + overflow-x: hidden; +} + +#search .results b { +padding-left: 2px; +} + +#search .results a { +padding: 1px 2px; +display: block; +cursor: pointer; +text-decoration: none; +color: #000; +} + +#search .results a:hover { +background-color: #999; +color: #fff; +} + + + +#attributeselect .select { + + background-color: #999; +} + + + +#attributeselect .list { +border: 1px solid black; +max-height: 200px; +overflow: scroll; + +} + + +.link h2 { +font-size: 1em; +padding-top: 1em; +} + +#mainpanel { + padding: 20px; +} + +#mainpanel dl { + padding-bottom:10px; +} + +#mainpanel h2 { + font-size:14px; +} + +#mainpanel dt { +width: 20px; +height: 20px; +float: left; +background-repeat: no-repeat; +background-image: url('../images/sprite.png'); +} + +#legend dl { +} + +#mainpanel h2 { + padding-bottom:10px; +} + +#legend dd { +margin-bottom: 8px; +color: #000; +} + +#mainpanel .infos dd { +margin-bottom: 12px; +} + +#mainpanel .node { +background-position: -11px -119px; +} + +#mainpanel .edge { +background-position: -51px -122px; +} + +#mainpanel .colours { + +background-image:url('../images/rainbow.png'); + +} +#legend .note { +margin-bottom: 8px; + +} + +#mainpanel .regions { +background-position: -171px -13px; +} + +#mainpanel .download { +background-position: -51px -13px; +} + +#mainpanel .moreinformation { +background: url('../images/info.png'); +background-repeat: no-repeat; +margin-left: 5px; +} + + +#zoom { + z-index:999; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + position: relative; + left: 90%; + bottom: 5%; +width: 60px; +} +.z { + width: 16px; + display: inline-block; + cursor:pointer; +} +.line { + font-size: 12px; + color: #000; + text-decoration: none; + font-weight: bold; + cursor: pointer; + cursor: hand; +} + +#information { +display: none; +background: #fff; +padding: 1px 10px 10px 10px; +} + +#information h3 { +margin: 14px 0 4px 0; +} + +#information p { +margin: 0 0 4px 0; +} + +#information .button { +width: 14px; +height: 14px; +background-image: url('../images/sprite.png'); +border: 1px solid #999; +display: inline-block; +*display: inline; +*zoom: 1; +} + +#information .button span { +display: none; +} + +#information .button.plus { +background-position: -91px -122px; +} + +#information .button.moins { +background-position: -131px -122px; +} + +#minify { +background-color: #fff; +padding: 4px 4px 4px 25px; +cursor: pointer; +background-image: url('../images/sprite.png'); +background-repeat: no-repeat; +background-position: -167px -118px; +position: absolute; +top: 65px; +left: 15px; +display: none; +} + +#minifier { +position: absolute; +width: 20px; +height: 16px; +background-image: url('../images/sprite.png'); +background-repeat: no-repeat; +background-position: -45px -147px; +cursor: pointer; +display: none; +} + +.input-icon { + position: absolute; + padding-top: 13px; + padding-left: 50px; +} +.box { + padding-bottom: 10%; + +} + +#websites { + list-style: none; /* Remove default bullets */ +} +#websites li { + list-style: none; +} +#websites li::before { + content: "\2588 "; /* Add content: \2022 is the CSS Code/unicode for a square block */ + font-weight: bold; /* If you want it to be bold */ + display: inline-block; /* Needed to add space between the bullet and the text */ + width: 1em; /* Also needed for space (tweak if needed) */ + margin-left: -1em; /* Also needed for space (tweak if needed) */ +} +.ui-all { + margin-left: 10px; +} +/* https://philipwalton.github.io/solved-by-flexbox/demos/holy-grail/ */ +.HolyGrail, +.HolyGrail-body { + display: flex; + flex-direction: column; +} + +.HolyGrail-nav { + order: -1; +} + +@media (min-width: 768px) { + .HolyGrail-body { + flex-direction: row; + flex: 1 0 auto; + } + .HolyGrail-content { + flex: 1 0 auto; + } + .HolyGrail-nav, .HolyGrail-ads { + /* 12em is the width of the columns */ + flex: 0 0 17em; + } +} diff --git a/html/observatory/css/tablet.css b/html/observatory/css/tablet.css new file mode 100644 index 0000000..f89216d --- /dev/null +++ b/html/observatory/css/tablet.css @@ -0,0 +1,3 @@ +#developercontainer { + display:none; +} \ No newline at end of file diff --git a/html/observatory/data/.keep b/html/observatory/data/.keep new file mode 100644 index 0000000..e69de29 diff --git a/html/observatory/images/blank.gif b/html/observatory/images/blank.gif new file mode 100644 index 0000000..35d42e8 Binary files /dev/null and b/html/observatory/images/blank.gif differ diff --git a/html/observatory/images/fancybox_sprite.png b/html/observatory/images/fancybox_sprite.png new file mode 100644 index 0000000..a1aae1a Binary files /dev/null and b/html/observatory/images/fancybox_sprite.png differ diff --git a/html/observatory/index.html b/html/observatory/index.html new file mode 100644 index 0000000..5a40c5d --- /dev/null +++ b/html/observatory/index.html @@ -0,0 +1,10 @@ + + + + + + + +This page has moved. Please click here if you are not automatically redirected to the new page. + + diff --git a/html/observatory/js/designsystem.min.js b/html/observatory/js/designsystem.min.js new file mode 100644 index 0000000..fccf6f9 --- /dev/null +++ b/html/observatory/js/designsystem.min.js @@ -0,0 +1 @@ +var AU=AU||{};!function(f){var e={};function u(e,t,n){if(e===t)return{stepSize:0,steps:0,intervalTime:0};var o=t-e,a=n/o,i=o<0?-1:1,l=Math.abs(o/i);return a=n/l,Math.abs(a)<1e3/60&&(a=1e3/60,i=o/(l=Math.ceil(Math.abs(n/a)))),{stepSize:i,steps:l-1,intervalTime:a}}"undefined"!=typeof module&&(e.CalculateAnimationSpecs=u),e.GetCSSPropertyBecauseIE=function(e,t){if("undefined"!=typeof getComputedStyle)return window.getComputedStyle(e)[t];var n=e.currentStyle[t];return"auto"===n&&(n=f.animate.CalculateAuto(e,t)),n},e.CalculateAuto=function(e,t){var n,o;return o="height"===t?(n=e.clientHeight,e.style[t]="auto",e.clientHeight):(n=e.clientWidth,e.style[t]="auto",e.clientWidth),e.style[t]=n+"px",parseInt(o)},e.Stop=function(e){clearInterval(e.AUanimation)},e.Run=function(i){var l=i.element,e=i.speed||250;l.length===undefined&&(l=[l]),"function"!=typeof i.callback&&(i.callback=function(){}),l[0].AUinteration=0,l[0].AUinterations=l.length;for(var t=0;t=l[0].AUinterations)return i.callback()}else n+=o.stepSize,e.style[i.property]=n+"px",o.steps--},Math.abs(o.intervalTime))}(n,o,c,r,a)}},e.Toggle=function(t){var n=t.element,e=t.property||"height",o=t.speed||250,a=t.closeSize===undefined?0:t.closeSize,i=t.openSize===undefined?"auto":t.openSize;n.length===undefined&&(n=[n]),"function"!=typeof t.prefunction&&(t.prefunction=function(){}),"function"!=typeof t.postfunction&&(t.postfunction=function(){}),"function"!=typeof t.callback&&(t.callback=function(){}),n[0].AUtoggleInteration=0,n[0].AUtoggleInterations=n.length;for(var l=0;lg;g++)for(var e=0;3>e;e++){for(var f=0,d=0;3>d;d++)f+=a[g][d]*b[d][e];c[g][e]=f}return c}function M(a,b){b.fillStyle=a.fillStyle;b.lineCap=a.lineCap;b.lineJoin=a.lineJoin;b.lineWidth=a.lineWidth;b.miterLimit=a.miterLimit;b.shadowBlur=a.shadowBlur;b.shadowColor=a.shadowColor;b.shadowOffsetX= +a.shadowOffsetX;b.shadowOffsetY=a.shadowOffsetY;b.strokeStyle=a.strokeStyle;b.globalAlpha=a.globalAlpha;b.font=a.font;b.textAlign=a.textAlign;b.textBaseline=a.textBaseline;b.arcScaleX_=a.arcScaleX_;b.arcScaleY_=a.arcScaleY_;b.lineScale_=a.lineScale_}function N(a){var b=a.indexOf("(",3),c=a.indexOf(")",b+1),b=a.substring(b+1,c).split(",");if(4!=b.length||"a"!=a.charAt(3))b[3]=1;return b}function B(a,b,c){return Math.min(c,Math.max(b,a))}function C(a,b,c){0>c&&c++;16*c?a+6*(b-a)*c: +1>2*c?b:2>3*c?a+6*(b-a)*(2/3-c):a}function D(a){if(a in E)return E[a];var b,c=1,a=""+a;if("#"==a.charAt(0))b=a;else if(/^rgb/.test(a)){c=N(a);b="#";for(var g,e=0;3>e;e++)g=-1!=c[e].indexOf("%")?Math.floor(255*(parseFloat(c[e])/100)):+c[e],b+=s[B(g,0,255)];c=+c[3]}else if(/^hsl/.test(a)){e=c=N(a);b=parseFloat(e[0])/360%360;0>b&&b++;g=B(parseFloat(e[1])/100,0,1);e=B(parseFloat(e[2])/100,0,1);if(0==g)g=e=b=e;else{var f=0.5>e?e*(1+g):e+g-e*g,d=2*e-f;g=C(d,f,b+1/3);e=C(d,f,b);b=C(d,f,b-1/3)}b="#"+s[Math.floor(255* +g)]+s[Math.floor(255*e)]+s[Math.floor(255*b)];c=c[3]}else b=W[a]||a;return E[a]={color:b,alpha:c}}function z(a){this.m_=A();this.mStack_=[];this.aStack_=[];this.currentPath_=[];this.fillStyle=this.strokeStyle="#000";this.lineWidth=1;this.lineJoin="miter";this.lineCap="butt";this.miterLimit=1*n;this.globalAlpha=1;this.font="10px sans-serif";this.textAlign="left";this.textBaseline="alphabetic";this.canvas=a;var b="width:"+a.clientWidth+"px;height:"+a.clientHeight+"px;overflow:hidden;position:absolute", +c=a.ownerDocument.createElement("div");c.style.cssText=b;a.appendChild(c);b=c.cloneNode(!1);b.style.backgroundColor="red";b.style.filter="alpha(opacity=0)";a.appendChild(b);this.element_=c;this.lineScale_=this.arcScaleY_=this.arcScaleX_=1}function O(a,b,c,g){a.currentPath_.push({type:"bezierCurveTo",cp1x:b.x,cp1y:b.y,cp2x:c.x,cp2y:c.y,x:g.x,y:g.y});a.currentX_=g.x;a.currentY_=g.y}function P(a,b){var c=D(a.strokeStyle),g=c.color,c=c.alpha*a.globalAlpha,e=a.lineScale_*a.lineWidth;1>e&&(c*=e);b.push("')}function Q(a,b,c,g){var e=a.fillStyle,f=a.arcScaleX_,d=a.arcScaleY_,h=g.x-c.x,l=g.y-c.y;if(e instanceof t){var i=0,j=g=0,r=0,k=1;if("gradient"==e.type_){var i=e.x1_/f,c=e.y1_/d,m=p(a,e.x0_/f,e.y0_/d),i=p(a,i,c),i=180*Math.atan2(i.x-m.x,i.y-m.y)/Math.PI;0>i&&(i+=360);1.0E-6>i&&(i=0)}else m=p(a,e.x0_,e.y0_),g=(m.x-c.x)/h,j=(m.y-c.y)/l,h/=f* +n,l/=d*n,k=u.max(h,l),r=2*e.r0_/k,k=2*e.r1_/k-r;f=e.colors_;f.sort(function(a,b){return a.offset-b.offset});for(var d=f.length,m=f[0].color,c=f[d-1].color,h=f[0].alpha*a.globalAlpha,a=f[d-1].alpha*a.globalAlpha,l=[],o=0;o')}else e instanceof +F?h&&l&&b.push("'):(e=D(a.fillStyle),b.push(''))}function p(a,b,c){a=a.m_;return{x:n*(b*a[0][0]+c*a[1][0]+a[2][0])-o,y:n*(b*a[0][1]+c*a[1][1]+a[2][1])-o}}function w(a,b,c){isFinite(b[0][0])&&isFinite(b[0][1])&&isFinite(b[1][0])&&isFinite(b[1][1])&&isFinite(b[2][0])&&isFinite(b[2][1])&&(a.m_=b,c&&(a.lineScale_=Y(Z(b[0][0]*b[1][1]-b[0][1]* +b[1][0]))))}function t(a){this.type_=a;this.r1_=this.y1_=this.x1_=this.r0_=this.y0_=this.x0_=0;this.colors_=[]}function F(a,b){if(!a||1!=a.nodeType||"IMG"!=a.tagName)throw new x("TYPE_MISMATCH_ERR");if("complete"!=a.readyState)throw new x("INVALID_STATE_ERR");switch(b){case "repeat":case null:case "":this.repetition_="repeat";break;case "repeat-x":case "repeat-y":case "no-repeat":this.repetition_=b;break;default:throw new x("SYNTAX_ERR");}this.src_=a.src;this.width_=a.width;this.height_=a.height} +function x(a){this.code=this[a];this.message=a+": DOM Exception "+this.code}var u=Math,h=u.round,G=u.sin,H=u.cos,Z=u.abs,Y=u.sqrt,n=10,o=n/2;navigator.userAgent.match(/MSIE ([\d.]+)?/);var J=Array.prototype.slice;L(document);var R={init:function(a){a=a||document;a.createElement("canvas");a.attachEvent("onreadystatechange",T(this.init_,this,a))},init_:function(a){for(var a=a.getElementsByTagName("canvas"),b=0;bd;d++)for(var y=0;16>y;y++)s[16*d+y]=d.toString(16)+y.toString(16);var W={aliceblue:"#F0F8FF",antiquewhite:"#FAEBD7",aquamarine:"#7FFFD4",azure:"#F0FFFF",beige:"#F5F5DC", +bisque:"#FFE4C4",black:"#000000",blanchedalmond:"#FFEBCD",blueviolet:"#8A2BE2",brown:"#A52A2A",burlywood:"#DEB887",cadetblue:"#5F9EA0",chartreuse:"#7FFF00",chocolate:"#D2691E",coral:"#FF7F50",cornflowerblue:"#6495ED",cornsilk:"#FFF8DC",crimson:"#DC143C",cyan:"#00FFFF",darkblue:"#00008B",darkcyan:"#008B8B",darkgoldenrod:"#B8860B",darkgray:"#A9A9A9",darkgreen:"#006400",darkgrey:"#A9A9A9",darkkhaki:"#BDB76B",darkmagenta:"#8B008B",darkolivegreen:"#556B2F",darkorange:"#FF8C00",darkorchid:"#9932CC",darkred:"#8B0000", +darksalmon:"#E9967A",darkseagreen:"#8FBC8F",darkslateblue:"#483D8B",darkslategray:"#2F4F4F",darkslategrey:"#2F4F4F",darkturquoise:"#00CED1",darkviolet:"#9400D3",deeppink:"#FF1493",deepskyblue:"#00BFFF",dimgray:"#696969",dimgrey:"#696969",dodgerblue:"#1E90FF",firebrick:"#B22222",floralwhite:"#FFFAF0",forestgreen:"#228B22",gainsboro:"#DCDCDC",ghostwhite:"#F8F8FF",gold:"#FFD700",goldenrod:"#DAA520",grey:"#808080",greenyellow:"#ADFF2F",honeydew:"#F0FFF0",hotpink:"#FF69B4",indianred:"#CD5C5C",indigo:"#4B0082", +ivory:"#FFFFF0",khaki:"#F0E68C",lavender:"#E6E6FA",lavenderblush:"#FFF0F5",lawngreen:"#7CFC00",lemonchiffon:"#FFFACD",lightblue:"#ADD8E6",lightcoral:"#F08080",lightcyan:"#E0FFFF",lightgoldenrodyellow:"#FAFAD2",lightgreen:"#90EE90",lightgrey:"#D3D3D3",lightpink:"#FFB6C1",lightsalmon:"#FFA07A",lightseagreen:"#20B2AA",lightskyblue:"#87CEFA",lightslategray:"#778899",lightslategrey:"#778899",lightsteelblue:"#B0C4DE",lightyellow:"#FFFFE0",limegreen:"#32CD32",linen:"#FAF0E6",magenta:"#FF00FF",mediumaquamarine:"#66CDAA", +mediumblue:"#0000CD",mediumorchid:"#BA55D3",mediumpurple:"#9370DB",mediumseagreen:"#3CB371",mediumslateblue:"#7B68EE",mediumspringgreen:"#00FA9A",mediumturquoise:"#48D1CC",mediumvioletred:"#C71585",midnightblue:"#191970",mintcream:"#F5FFFA",mistyrose:"#FFE4E1",moccasin:"#FFE4B5",navajowhite:"#FFDEAD",oldlace:"#FDF5E6",olivedrab:"#6B8E23",orange:"#FFA500",orangered:"#FF4500",orchid:"#DA70D6",palegoldenrod:"#EEE8AA",palegreen:"#98FB98",paleturquoise:"#AFEEEE",palevioletred:"#DB7093",papayawhip:"#FFEFD5", +peachpuff:"#FFDAB9",peru:"#CD853F",pink:"#FFC0CB",plum:"#DDA0DD",powderblue:"#B0E0E6",rosybrown:"#BC8F8F",royalblue:"#4169E1",saddlebrown:"#8B4513",salmon:"#FA8072",sandybrown:"#F4A460",seagreen:"#2E8B57",seashell:"#FFF5EE",sienna:"#A0522D",skyblue:"#87CEEB",slateblue:"#6A5ACD",slategray:"#708090",slategrey:"#708090",snow:"#FFFAFA",springgreen:"#00FF7F",steelblue:"#4682B4",tan:"#D2B48C",thistle:"#D8BFD8",tomato:"#FF6347",turquoise:"#40E0D0",violet:"#EE82EE",wheat:"#F5DEB3",whitesmoke:"#F5F5F5",yellowgreen:"#9ACD32"}, +E={},I={},X={butt:"flat",round:"round"},d=z.prototype;d.clearRect=function(){this.textMeasureEl_&&(this.textMeasureEl_.removeNode(!0),this.textMeasureEl_=null);this.element_.innerHTML=""};d.beginPath=function(){this.currentPath_=[]};d.moveTo=function(a,b){var c=p(this,a,b);this.currentPath_.push({type:"moveTo",x:c.x,y:c.y});this.currentX_=c.x;this.currentY_=c.y};d.lineTo=function(a,b){var c=p(this,a,b);this.currentPath_.push({type:"lineTo",x:c.x,y:c.y});this.currentX_=c.x;this.currentY_=c.y};d.bezierCurveTo= +function(a,b,c,g,e,f){e=p(this,e,f);a=p(this,a,b);c=p(this,c,g);O(this,a,c,e)};d.quadraticCurveTo=function(a,b,c,g){a=p(this,a,b);c=p(this,c,g);g={x:this.currentX_+2/3*(a.x-this.currentX_),y:this.currentY_+2/3*(a.y-this.currentY_)};O(this,g,{x:g.x+(c.x-this.currentX_)/3,y:g.y+(c.y-this.currentY_)/3},c)};d.arc=function(a,b,c,g,e,f){var c=c*n,d=f?"at":"wa",h=a+H(g)*c-o,l=b+G(g)*c-o,g=a+H(e)*c-o,e=b+G(e)*c-o;h==g&&!f&&(h+=0.125);a=p(this,a,b);h=p(this,h,l);g=p(this,g,e);this.currentPath_.push({type:d, +x:a.x,y:a.y,radius:c,xStart:h.x,yStart:h.y,xEnd:g.x,yEnd:g.y})};d.rect=function(a,b,c,g){this.moveTo(a,b);this.lineTo(a+c,b);this.lineTo(a+c,b+g);this.lineTo(a,b+g);this.closePath()};d.strokeRect=function(a,b,c,g){var e=this.currentPath_;this.beginPath();this.moveTo(a,b);this.lineTo(a+c,b);this.lineTo(a+c,b+g);this.lineTo(a,b+g);this.closePath();this.stroke();this.currentPath_=e};d.fillRect=function(a,b,c,g){var e=this.currentPath_;this.beginPath();this.moveTo(a,b);this.lineTo(a+c,b);this.lineTo(a+ +c,b+g);this.lineTo(a,b+g);this.closePath();this.fill();this.currentPath_=e};d.createLinearGradient=function(a,b,c,g){var e=new t("gradient");e.x0_=a;e.y0_=b;e.x1_=c;e.y1_=g;return e};d.createRadialGradient=function(a,b,c,g,e,f){var d=new t("gradientradial");d.x0_=a;d.y0_=b;d.r0_=c;d.x1_=g;d.y1_=e;d.r1_=f;return d};d.drawImage=function(a,b){var c,g,e,d,o,v,l,i;e=a.runtimeStyle.width;d=a.runtimeStyle.height;a.runtimeStyle.width="auto";a.runtimeStyle.height="auto";var j=a.width,r=a.height;a.runtimeStyle.width= +e;a.runtimeStyle.height=d;if(3==arguments.length)c=arguments[1],g=arguments[2],o=v=0,l=e=j,i=d=r;else if(5==arguments.length)c=arguments[1],g=arguments[2],e=arguments[3],d=arguments[4],o=v=0,l=j,i=r;else if(9==arguments.length)o=arguments[1],v=arguments[2],l=arguments[3],i=arguments[4],c=arguments[5],g=arguments[6],e=arguments[7],d=arguments[8];else throw Error("Invalid number of arguments");var k=p(this,c,g),m=[];m.push(" ','","");this.element_.insertAdjacentHTML("BeforeEnd",m.join(""))};d.stroke=function(a){var b=[];b.push("d.x)d.x=f.x;if(null==c.y||f.yd.y)d.y=f.y}}b.push(' ">');a?Q(this,b,c,d):P(this,b);b.push("");this.element_.insertAdjacentHTML("beforeEnd",b.join(""))};d.fill=function(){this.stroke(!0)};d.closePath=function(){this.currentPath_.push({type:"close"})};d.save=function(){var a= +{};M(this,a);this.aStack_.push(a);this.mStack_.push(this.m_);this.m_=q(A(),this.m_)};d.restore=function(){this.aStack_.length&&(M(this.aStack_.pop(),this),this.m_=this.mStack_.pop())};d.translate=function(a,b){w(this,q([[1,0,0],[0,1,0],[a,b,1]],this.m_),!1)};d.rotate=function(a){var b=H(a),a=G(a);w(this,q([[b,a,0],[-a,b,0],[0,0,1]],this.m_),!1)};d.scale=function(a,b){this.arcScaleX_*=a;this.arcScaleY_*=b;w(this,q([[a,0,0],[0,b,0],[0,0,1]],this.m_),!0)};d.transform=function(a,b,c,d,e,f){w(this,q([[a, +b,0],[c,d,0],[e,f,1]],this.m_),!0)};d.setTransform=function(a,b,c,d,e,f){w(this,[[a,b,0],[c,d,0],[e,f,1]],!0)};d.drawText_=function(a,b,c,d,e){var f=this.m_,d=0,o=1E3,q=0,l=[],i;i=this.font;if(I[i])i=I[i];else{var j=document.createElement("div").style;try{j.font=i}catch(r){}i=I[i]={style:j.fontStyle||"normal",variant:j.fontVariant||"normal",weight:j.fontWeight||"normal",size:j.fontSize||10,family:j.fontFamily||"sans-serif"}}var j=i,k=this.element_;i={};for(var m in j)i[m]=j[m];m=parseFloat(k.currentStyle.fontSize); +k=parseFloat(j.size);i.size="number"==typeof j.size?j.size:-1!=j.size.indexOf("px")?k:-1!=j.size.indexOf("em")?m*k:-1!=j.size.indexOf("%")?m/100*k:-1!=j.size.indexOf("pt")?k/0.75:m;i.size*=0.981;m=i.style+" "+i.variant+" "+i.weight+" "+i.size+"px "+i.family;k=this.element_.currentStyle;j=this.textAlign.toLowerCase();switch(j){case "left":case "center":case "right":break;case "end":j="ltr"==k.direction?"right":"left";break;case "start":j="rtl"==k.direction?"right":"left";break;default:j="left"}switch(this.textBaseline){case "hanging":case "top":q= +i.size/1.75;break;case "middle":break;default:case null:case "alphabetic":case "ideographic":case "bottom":q=-i.size/2.25}switch(j){case "right":d=1E3;o=0.05;break;case "center":d=o=500}b=p(this,b+0,c+q);l.push('');e?P(this,l):Q(this,l,{x:-d,y:0},{x:o,y:i.size});e=f[0][0].toFixed(3)+","+f[1][0].toFixed(3)+","+f[0][1].toFixed(3)+ +","+f[1][1].toFixed(3)+",0,0";b=h(b.x/n)+","+h(b.y/n);l.push('','','');this.element_.insertAdjacentHTML("beforeEnd",l.join(""))};d.fillText=function(a,b,c,d){this.drawText_(a,b,c,d,!1)};d.strokeText=function(a,b,c,d){this.drawText_(a,b,c,d,!0)};d.measureText=function(a){this.textMeasureEl_||(this.element_.insertAdjacentHTML("beforeEnd", +''),this.textMeasureEl_=this.element_.lastChild);var b=this.element_.ownerDocument;this.textMeasureEl_.innerHTML="";this.textMeasureEl_.style.font=this.font;this.textMeasureEl_.appendChild(b.createTextNode(a));return{width:this.textMeasureEl_.offsetWidth}};d.clip=function(){};d.arcTo=function(){};d.createPattern=function(a,b){return new F(a,b)};t.prototype.addColorStop=function(a,b){b=D(b);this.colors_.push({offset:a, +color:b.color,alpha:b.alpha})};d=x.prototype=Error();d.INDEX_SIZE_ERR=1;d.DOMSTRING_SIZE_ERR=2;d.HIERARCHY_REQUEST_ERR=3;d.WRONG_DOCUMENT_ERR=4;d.INVALID_CHARACTER_ERR=5;d.NO_DATA_ALLOWED_ERR=6;d.NO_MODIFICATION_ALLOWED_ERR=7;d.NOT_FOUND_ERR=8;d.NOT_SUPPORTED_ERR=9;d.INUSE_ATTRIBUTE_ERR=10;d.INVALID_STATE_ERR=11;d.SYNTAX_ERR=12;d.INVALID_MODIFICATION_ERR=13;d.NAMESPACE_ERR=14;d.INVALID_ACCESS_ERR=15;d.VALIDATION_ERR=16;d.TYPE_MISMATCH_ERR=17;G_vmlCanvasManager=R;CanvasRenderingContext2D=z;CanvasGradient= +t;CanvasPattern=F;DOMException=x}(); \ No newline at end of file diff --git a/html/observatory/js/main.js b/html/observatory/js/main.js new file mode 100644 index 0000000..93e0935 --- /dev/null +++ b/html/observatory/js/main.js @@ -0,0 +1,720 @@ +var sigInst, canvas, $GP; +var colorBrewer2Set3 = [ + "#8dd3c7", + "#ffffb3", + "#bebada", + "#fb8072", + "#80b1d3", + "#fdb462", + "#b3de69", + "#fccde5", + "#d9d9d9", + "#bc80bd", + "#ccebc5", + "#ffed6f" +]; // http://colorbrewer2.org/#type=qualitative&scheme=Set3&n=12 +//Load configuration file +var config = {}; + +//For debug allow a config=file.json parameter to specify the config +function GetQueryStringParams(sParam, defaultVal) { + var sPageURL = "" + window.location; //.search.substring(1);//This might be causing error in Safari? + if (sPageURL.indexOf("?") == -1) return defaultVal; + sPageURL = sPageURL.substr(sPageURL.indexOf("?") + 1); + var sURLVariables = sPageURL.split("&"); + for (var i = 0; i < sURLVariables.length; i++) { + var sParameterName = sURLVariables[i].split("="); + if (sParameterName[0] == sParam) { + return sParameterName[1]; + } + } + return defaultVal; +} + +jQuery.getJSON(GetQueryStringParams("config", "config.json"), function( + data, + textStatus, + jqXHR +) { + config = data; + + if (config.type != "network") { + //bad config + alert("Invalid configuration settings."); + return; + } + + //As soon as page is ready (and data ready) set up it + $(document).ready(setupGUI(config)); +}); //End JSON Config load + +// FUNCTION DECLARATIONS + +Object.size = function(obj) { + var size = 0, + key; + for (key in obj) { + if (obj.hasOwnProperty(key)) size++; + } + return size; +}; + +function initSigma(config) { + var data = config.data; + + var drawProps, graphProps, mouseProps; + // https://github.com/jacomyal/sigma.js/wiki/Settings + + if (config.sigma && config.sigma.drawingProperties) + drawProps = config.sigma.drawingProperties; + else + drawProps = { + defaultLabelColor: "#000", + defaultLabelSize: 10, + defaultLabelBGColor: "#ddd", + defaultHoverLabelBGColor: "#002147", + defaultLabelHoverColor: "#fff", + labelThreshold: 100, + defaultEdgeType: "curve", + edgeColor: "source", + hoverFontStyle: "bold", + fontStyle: "bold", + activeFontStyle: "bold", + borderSize: 2, //Something other than 0 + nodeBorderColor: "default", //exactly like this + defaultNodeBorderColor: "#000", //Any color of your choice + defaultBorderView: "always" //apply the default color to all nodes always (normal+hover) + }; + + if (config.sigma && config.sigma.graphProperties) + graphProps = config.sigma.graphProperties; + else + graphProps = { + minNodeSize: 1, + maxNodeSize: 20, + minEdgeSize: 0.2, + maxEdgeSize: 0.5 + }; + + if (config.sigma && config.sigma.mouseProperties) + mouseProps = config.sigma.mouseProperties; + else + mouseProps = { + minRatio: 0.75, // How far can we zoom out? + maxRatio: 20 // How far can we zoom in? + }; + + var a = sigma + .init(document.getElementById("sigma-canvas")) + .drawingProperties(drawProps) + .graphProperties(graphProps) + .mouseProperties(mouseProps); + sigInst = a; + a.active = false; + a.neighbors = {}; + a.detail = false; + + dataReady = function() { + //This is called as soon as data is loaded + a.clusters = {}; + a.iterEdges(function(b) { + b.attr["true_color"] = b.color; + }); + a.iterNodes(function(b) { + //This is where we populate the array used for the group select box + + // note: index may not be consistent for all nodes. Should calculate each time. + // note: index may not be consistent for all nodes. Should calculate each time. + // alert(JSON.stringify(b.attr.attributes[5].val)); + // alert(b.x); + b.attr["true_color"] = b.color; + // if (b.id.endsWith("()")) { + // b.attr['drawBorder'] = true; + // } + a.clusters[b.attr.attributes.domain] || + (a.clusters[b.attr.attributes.domain] = []); + a.clusters[b.attr.attributes.domain].push(b.id); //SAH: push id not label + }); + + // a.bind("upnodes", function(a) { + // nodeActive(a.content[0]); + // }); + + a.draw(); + configSigmaElements(config); + }; + + if (data.indexOf("gexf") > 0 || data.indexOf("xml") > 0) + a.parseGexf("data/" + data, dataReady); + else a.parseJson("data/" + data, dataReady); + gexf = sigmaInst = null; +} + +function setupGUI(config) { + // Initialise main interface elements + $("#agencyName").html(config.agency.name); + // Node + if (config.legend.nodeLabel) { + $(".node") + .next() + .html(config.legend.nodeLabel); + } else { + //hide more information link + $(".node").hide(); + } + // Edge + if (config.legend.edgeLabel) { + $(".edge") + .next() + .html(config.legend.edgeLabel); + } else { + //hide more information link + $(".edge").hide(); + } + // Colours + if (config.legend.nodeLabel) { + $(".colours") + .next() + .html(config.legend.colorLabel); + } else { + //hide more information link + $(".colours").hide(); + } + $.each(config.agency.websites, function(i) { + var li = $("
  • ") + .css("color", colorBrewer2Set3[i]) + .addClass("ui-menu-item") + .attr("role", "menuitem") + .appendTo($("#websites")); + + var aaa = $("") + .addClass("ui-all") + .text(config.agency.websites[i]) + .attr("href", "#" + config.agency.websites[i]) + .click(function() { + showCluster(config.agency.websites[i]); + }) + .appendTo(li); + }); + $GP = { + calculating: false, + showgroup: false + }; + $GP.intro = $("#intro"); + $GP.minifier = $GP.intro.find("#minifier"); + $GP.mini = $("#minify"); + $GP.info = $("#attributepane"); + $GP.info_donnees = $GP.info.find(".nodeattributes"); + $GP.info_name = $GP.info.find(".name"); + $GP.info_link = $GP.info.find(".link"); + $GP.info_data = $GP.info.find(".data"); + $GP.info_close = $GP.info.find(".returntext"); + $GP.info_close2 = $GP.info.find(".close"); + $GP.info_p = $GP.info.find(".p"); + $GP.info_close.click(nodeNormal); + $GP.info_close2.click(nodeNormal); + $GP.form = $("#mainpanel").find("form"); + $GP.search = new Search($GP.form.find("#search")); + if (!config.features.search.enabled == true) { + $("#search").hide(); + } + if (!config.features.groupSelector.enabled == true) { + $("#attributeselect").hide(); + } + $GP.cluster = new Cluster($GP.form.find("#attributeselect")); + config.GP = $GP; + initSigma(config); +} + +function configSigmaElements(config) { + $GP = config.GP; + + $GP.bg = $(sigInst._core.domElements.bg); + $GP.bg2 = $(sigInst._core.domElements.bg2); + var clusterList = [], + clusterDomain; + for (clusterDomain in sigInst.clusters) { + clusterList.push( + '" + ); + } + //a.sort(); + $GP.cluster.content(clusterList.join("")); + + $("#zoom") + .find(".z") + .each(function() { + var a = $(this), + b = a.attr("rel"); + a.click(function() { + if (b == "center") { + sigInst.position(0, 0, 1).draw(); + } else { + var a = sigInst._core; + sigInst.zoomTo( + a.domElements.nodes.width / 2, + a.domElements.nodes.height / 2, + a.mousecaptor.ratio * ("in" == b ? 1.5 : 0.5) + ); + } + }); + }); + $GP.mini.click(function() { + $GP.mini.hide(); + $GP.intro.show(); + $GP.minifier.show(); + }); + $GP.minifier.click(function() { + $GP.intro.hide(); + $GP.minifier.hide(); + $GP.mini.show(); + }); + $GP.intro.find("#showGroups").click(function() { + true == $GP.showgroup ? showGroups(false) : showGroups(true); + }); + clusterList = window.location.hash.substr(1); + if (0 < clusterList.length) + switch (clusterList) { + case "Groups": + showGroups(true); + break; + case "information": + $.fancybox.open($("#information"), clusterDomain); + break; + default: + ($GP.search.exactMatch = true), $GP.search.search(clusterList); + $GP.search.clean(); + } +} + +function Search(a) { + this.input = a.find("input[name=search]"); + this.state = a.find(".state"); + this.results = a.find(".results"); + this.exactMatch = false; + this.lastSearch = ""; + this.searching = false; + var b = this; + this.input.focus(function() { + var a = $(this); + a.data("focus") || (a.data("focus", true), a.removeClass("empty")); + b.clean(); + }); + this.input.keydown(function(a) { + if (13 == a.which) + return b.state.addClass("searching"), b.search(b.input.val()), false; + }); + this.state.click(function() { + var a = b.input.val(); + b.searching && a == b.lastSearch + ? b.close() + : (b.state.addClass("searching"), b.search(a)); + }); + this.dom = a; + this.close = function() { + this.state.removeClass("searching"); + this.results.hide(); + this.searching = false; + this.input.val(""); //SAH -- let's erase string when we close + nodeNormal(); + }; + this.clean = function() { + this.results.empty().hide(); + this.state.removeClass("searching"); + this.input.val(""); + }; + this.search = function(a) { + var b = false, + c = [], + b = this.exactMatch ? ("^" + a + "$").toLowerCase() : a.toLowerCase(), + g = RegExp(b); + this.exactMatch = false; + this.searching = true; + this.lastSearch = a; + this.results.empty(); + if (2 >= a.length) + this.results.html( + "You must search for a name with a minimum of 3 letters." + ); + else { + sigInst.iterNodes(function(a) { + g.test(a.label.toLowerCase()) && + c.push({ + id: a.id, + name: a.label + }); + }); + c.length ? ((b = true), nodeActive(c[0].id)) : (b = showCluster(a)); + a = ["Search Results: "]; + if (1 < c.length) + for (var d = 0, h = c.length; d < h; d++) + a.push( + '" + + c[d].name + + "" + ); + 0 == c.length && !b && a.push("No results found."); + 1 < a.length && this.results.html(a.join("")); + } + if (c.length != 1) this.results.show(); + if (c.length == 1) this.results.hide(); + }; +} + +function Cluster(a) { + this.cluster = a; + this.display = false; + this.list = this.cluster.find(".list"); + this.list.empty(); + + this.toggle = function() { + this.display ? this.hide() : this.show(); + }; + this.content = function(a) { + this.list.html(a); + this.list.find("a").click(function() { + var a = $(this) + .attr("href") + .substr(1); + showCluster(a); + }); + }; +} +function showGroups(a) { + a + ? ($GP.intro.find("#showGroups").text("Hide groups"), + $GP.bg.show(), + $GP.bg2.hide(), + ($GP.showgroup = true)) + : ($GP.intro.find("#showGroups").text("View Groups"), + $GP.bg.hide(), + $GP.bg2.show(), + ($GP.showgroup = false)); +} + +function nodeNormal() { + if (true != $GP.calculating && false != sigInst.detail) { + sigInst.drawingProperties("edgeColor", "source"); + showGroups(false); + $GP.calculating = true; + sigInst.detail = true; + $GP.info.hide(); + sigInst.iterEdges(function(a) { + a.attr.color = false; + a.hidden = false; + a.color = a.attr["true_color"]; + a.attr["grey"] = false; + }); + sigInst.iterNodes(function(a) { + a.attr["drawBorder"] = false; + a.hidden = false; + a.attr.color = false; + a.attr.lineWidth = false; + a.attr.size = false; + a.color = a.attr["true_color"]; + a.attr["grey"] = false; + }); + sigInst.draw(2, 2, 2, 2); + sigInst.neighbors = {}; + sigInst.active = false; + $GP.calculating = false; + window.location.hash = ""; + } +} + +function nodeActive(a) { + var groupByDirection = false; + if ( + config.informationPanel.groupByEdgeDirection && + config.informationPanel.groupByEdgeDirection == true + ) + groupByDirection = true; + + sigInst.neighbors = {}; + sigInst.detail = !0; + var b = sigInst._core.graph.nodesIndex[a]; + showGroups(!1); + var outgoing = {}, + incoming = {}, + mutual = {}; //SAH + sigInst.iterEdges(function(b) { + b.attr.lineWidth = !1; + b.hidden = !0; + + n = { + name: b.label, + colour: b.color + }; + + if (a == b.source) outgoing[b.target] = n; + //SAH + else if (a == b.target) incoming[b.source] = n; //SAH + if (a == b.source || a == b.target) + sigInst.neighbors[a == b.target ? b.source : b.target] = n; + (b.hidden = false), (b.attr.color = "rgba(0, 0, 0, 1)"); + }); + var f = []; + sigInst.iterNodes(function(a) { + a.hidden = true; + a.attr.lineWidth = false; + a.attr.color = a.color; + }); + + if (groupByDirection) { + //SAH - Compute intersection for mutual and remove these from incoming/outgoing + for (e in outgoing) { + //name=outgoing[e]; + if (e in incoming) { + mutual[e] = outgoing[e]; + delete incoming[e]; + delete outgoing[e]; + } + } + } + + var createList = function(c) { + var f = []; + var e = [], + //c = sigInst.neighbors, + g; + for (g in c) { + var d = sigInst._core.graph.nodesIndex[g]; + d.hidden = !1; + d.attr.lineWidth = !1; + d.attr.color = c[g].colour; + a != g && + e.push({ + id: g, + name: d.label, + group: c[g].name ? c[g].name : "", + colour: c[g].colour + }); + } + e.sort(function(a, b) { + var c = a.group.toLowerCase(), + d = b.group.toLowerCase(), + e = a.name.toLowerCase(), + f = b.name.toLowerCase(); + return c != d ? (c < d ? -1 : c > d ? 1 : 0) : e < f ? -1 : e > f ? 1 : 0; + }); + d = ""; + for (g in e) { + c = e[g]; + /*if (c.group != d) { + d = c.group; + f.push('
  • ' + d + "
  • "); + }*/ + f.push( + '
  • ' + + c.name + + "
  • " + ); + } + return f; + }; + + /*console.log("mutual:"); + console.log(mutual); + console.log("incoming:"); + console.log(incoming); + console.log("outgoing:"); + console.log(outgoing);*/ + + var f = []; + + //console.log("neighbors:"); + //console.log(sigInst.neighbors); + + if (groupByDirection) { + size = Object.size(mutual); + f.push("

    Mututal (" + size + ")

    "); + size > 0 + ? (f = f.concat(createList(mutual))) + : f.push("No mutual links
    "); + size = Object.size(incoming); + f.push("

    Incoming (" + size + ")

    "); + size > 0 + ? (f = f.concat(createList(incoming))) + : f.push("No incoming links
    "); + size = Object.size(outgoing); + f.push("

    Outgoing (" + size + ")

    "); + size > 0 + ? (f = f.concat(createList(outgoing))) + : f.push("No outgoing links
    "); + } else { + f = f.concat(createList(sigInst.neighbors)); + } + //b is object of active node -- SAH + b.hidden = false; + b.attr.color = b.color; + b.attr.lineWidth = 6; + b.attr.strokeStyle = "#000000"; + sigInst.draw(2, 2, 2, 2); + + $GP.info_link.find("ul").html(f.join("")); + $GP.info_link.find("li").each(function() { + var a = $(this), + b = a.attr("rel"); + }); + f = b.attr; + if (f.attributes) { + var image_attribute = false; + if (config.informationPanel.imageAttribute) { + image_attribute = config.informationPanel.imageAttribute; + } + e = []; + temp_array = []; + g = 0; + for (var attr in f.attributes) { + var d = f.attributes[attr], + h = ""; + if (attr != image_attribute) { + h = "" + attr + ": " + d + "
    "; + } + //temp_array.push(f.attributes[g].attr); + e.push(h); + } + + if (image_attribute) { + //image_index = jQuery.inArray(image_attribute, temp_array); + $GP.info_name.html( + "
    ' + + b.label + + "
    " + ); + } else { + $GP.info_name.html( + "
    ' + + b.label + + "
    " + ); + } + // Image field for attribute pane + $GP.info_data.html(e.join("
    ")); + } + $GP.info_data.show(); + $GP.info_p.html("Connections:"); + $GP.info.show(); + $GP.info_donnees.hide(); + $GP.info_donnees.show(); + sigInst.active = a; + window.location.hash = b.label; +} + +function showCluster(a) { + var b = sigInst.clusters[a]; + if (b && 0 < b.length) { + //showGroups(false); + sigInst.drawingProperties("edgeColor", "default"); + sigInst.detail = true; + b.sort(); + sigInst.iterEdges(function(a) { + a.hidden = false; + a.attr.lineWidth = false; + a.attr.color = false; + a.color = a.attr["true_color"]; + a.attr["grey"] = 1; + }); + + sigInst.iterNodes(function(n) { + n.attr["grey"] = 1; + n.attr["drawBorder"] = true; + }); + var clusterIds = []; + var toBeMoved = []; + for (var f = [], clusters = [], c = 0, g = b.length; c < g; c++) { + var d = sigInst._core.graph.nodesIndex[b[c]]; + if (d.attr["grey"]) { + clusters.push(b[c]); + + d.attr.lineWidth = true; + f.push( + '
  • ' + + d.label.replace(a, "").replace(/\/\//g, "/") + + "
  • " + ); + + d.attr["drawBorder"] = false; + if (config.agency.websites.indexOf(a)> -1) { + d.color = colorBrewer2Set3[config.agency.websites.indexOf(a)]; + } else { + d.color="red"; + + } + d.attr["grey"] = false; + toBeMoved.push( + sigInst._core.graph.nodes.findIndex(function(e) { + return e.id == d.id; + }) + ); + clusterIds.push(d.id); + } + } + sigInst.iterEdges(function(edge) { + if ( + clusterIds.indexOf(edge.target) >= 0 || + clusterIds.indexOf(edge.source) >= 0 + ) { + if (config.agency.websites.indexOf(a)>-1) { + d.color = colorBrewer2Set3[config.agency.websites.indexOf(a)]; + } else { + d.color="red"; + + } + edge.attr["grey"] = false; + } + }); + toBeMoved.forEach(function(m) { + moved = sigInst._core.graph.nodes.splice(m, 1); + sigInst._core.graph.nodes.push(moved[0]); + //sigInst._core.graph.nodesIndex[moved[0].id] = sigInst._core.graph.nodes.length; + }); + + sigInst.clusters[a] = clusters; + sigInst.refresh(); + sigInst.draw(2, 2, 2, 2); + $GP.info_name.html("" + a + ""); + $GP.info_data.hide(); + $GP.info_p.html("Pages:"); + $GP.info_link.find("ul").html(f.join("")); + $GP.info.show(); + $GP.search.clean(); + return true; + } + return false; +} diff --git a/html/observatory/js/sigma/sigma.min.js b/html/observatory/js/sigma/sigma.min.js new file mode 100644 index 0000000..182f3e8 --- /dev/null +++ b/html/observatory/js/sigma/sigma.min.js @@ -0,0 +1,1800 @@ +/* sigmajs.org - an open-source light-weight JavaScript graph drawing library - Version: 0.1 - Author: Alexis Jacomy - License: MIT */ +var sigma = { tools: {}, classes: {}, instances: {} }; +(function() { + Array.prototype.some || + (Array.prototype.some = function(g, i) { + var k = this.length; + if ("function" != typeof g) throw new TypeError(); + for (var m = 0; m < k; m++) + if (m in this && g.call(i, this[m], m, this)) return !0; + return !1; + }); + Array.prototype.forEach || + (Array.prototype.forEach = function(g, i) { + var k = this.length; + if (typeof g != "function") throw new TypeError(); + for (var m = 0; m < k; m++) m in this && g.call(i, this[m], m, this); + }); + Array.prototype.map || + (Array.prototype.map = function(g, i) { + var k = this.length; + if (typeof g != "function") throw new TypeError(); + for (var m = Array(k), b = 0; b < k; b++) + b in this && (m[b] = g.call(i, this[b], b, this)); + return m; + }); + Array.prototype.filter || + (Array.prototype.filter = function(g, i) { + var k = this.length; + if (typeof g != "function") throw new TypeError(); + for (var m = [], b = 0; b < k; b++) + if (b in this) { + var j = this[b]; + g.call(i, j, b, this) && m.push(j); + } + return m; + }); + if (!Object.keys) { + var i = Object, + q = Object.prototype.hasOwnProperty, + g = !{ toString: null }.propertyIsEnumerable("toString"), + p = "toString toLocaleString valueOf hasOwnProperty isPrototypeOf propertyIsEnumerable constructor".split( + " " + ), + z = p.length; + i.keys = function(i) { + if ((typeof i !== "object" && typeof i !== "function") || i === null) + throw new TypeError("Object.keys called on non-object"); + var x = [], + k; + for (k in i) q.call(i, k) && x.push(k); + if (g) for (k = 0; k < z; k++) q.call(i, p[k]) && x.push(p[k]); + return x; + }; + } +})(); +sigma.classes.Cascade = function() { + this.p = {}; + this.config = function(i, q) { + if ("string" == typeof i && void 0 == q) return this.p[i]; + var g = "object" == typeof i && void 0 == q ? i : {}; + "string" == typeof i && (g[i] = q); + for (var p in g) void 0 != this.p[p] && (this.p[p] = g[p]); + return this; + }; +}; +sigma.classes.EventDispatcher = function() { + var i = {}, + q = this; + this.one = function(g, p) { + if (!p || !g) return q; + ("string" == typeof g ? g.split(" ") : g).forEach(function(g) { + i[g] || (i[g] = []); + i[g].push({ h: p, one: !0 }); + }); + return q; + }; + this.bind = function(g, p) { + if (!p || !g) return q; + ("string" == typeof g ? g.split(" ") : g).forEach(function(g) { + i[g] || (i[g] = []); + i[g].push({ h: p, one: !1 }); + }); + return q; + }; + this.unbind = function(g, p) { + g || (i = {}); + var z = "string" == typeof g ? g.split(" ") : g; + p + ? z.forEach(function(g) { + i[g] && + (i[g] = i[g].filter(function(g) { + return g.h != p; + })); + i[g] && 0 == i[g].length && delete i[g]; + }) + : z.forEach(function(g) { + delete i[g]; + }); + return q; + }; + this.dispatch = function(g, p) { + i[g] && + (i[g].forEach(function(i) { + i.h({ type: g, content: p, target: q }); + }), + (i[g] = i[g].filter(function(g) { + return !g.one; + }))); + return q; + }; +}; +(function() { + function i() { + function b(a) { + return { + x: a.x, + y: a.y, + size: a.size, + degree: a.degree, + inDegree: a.inDegree, + outDegree: a.outDegree, + displayX: a.displayX, + displayY: a.displayY, + displaySize: a.displaySize, + label: a.label, + id: a.id, + color: a.color, + fixed: a.fixed, + active: a.active, + hidden: a.hidden, + forceLabel: a.forceLabel, + attr: a.attr + }; + } + function j(a) { + return { + source: a.source.id, + target: a.target.id, + size: a.size, + type: a.type, + weight: a.weight, + displaySize: a.displaySize, + label: a.label, + hidden: a.hidden, + id: a.id, + attr: a.attr, + color: a.color + }; + } + function f() { + c.nodes = []; + c.nodesIndex = {}; + c.edges = []; + c.edgesIndex = {}; + return c; + } + sigma.classes.Cascade.call(this); + sigma.classes.EventDispatcher.call(this); + var c = this; + this.p = { + minNodeSize: 0, + maxNodeSize: 0, + minEdgeSize: 0, + maxEdgeSize: 0, + scalingMode: "inside", + nodesPowRatio: 0.5, + edgesPowRatio: 0 + }; + this.borders = {}; + f(); + this.addNode = function(a, b) { + if (c.nodesIndex[a]) throw Error('Node "' + a + '" already exists.'); + var b = b || {}, + d = { + x: 0, + y: 0, + size: 1, + degree: 0, + inDegree: 0, + outDegree: 0, + fixed: !1, + active: !1, + hidden: !1, + forceLabel: !1, + label: a.toString(), + id: a.toString(), + attr: {} + }, + f; + for (f in b) + switch (f) { + case "id": + break; + case "x": + case "y": + case "size": + d[f] = +b[f]; + break; + case "fixed": + case "active": + case "hidden": + case "forceLabel": + d[f] = !!b[f]; + break; + case "color": + case "label": + d[f] = b[f]; + break; + default: + d.attr[f] = b[f]; + } + c.nodes.push(d); + c.nodesIndex[a.toString()] = d; + return c; + }; + this.addEdge = function(a, b, d, f) { + if (c.edgesIndex[a]) throw Error('Edge "' + a + '" already exists.'); + if (!c.nodesIndex[b]) + throw Error("Edge's source \"" + b + '" does not exist yet.'); + if (!c.nodesIndex[d]) + throw Error("Edge's target \"" + d + '" does not exist yet.'); + f = f || {}; + b = { + source: c.nodesIndex[b], + target: c.nodesIndex[d], + size: 1, + weight: 1, + displaySize: 0.5, + label: a.toString(), + id: a.toString(), + hidden: !1, + attr: {} + }; + b.source.degree++; + b.source.outDegree++; + b.target.degree++; + b.target.inDegree++; + for (var o in f) + switch (o) { + case "id": + case "source": + case "target": + break; + case "hidden": + b[o] = !!f[o]; + break; + case "size": + case "weight": + b[o] = +f[o]; + break; + case "color": + b[o] = f[o].toString(); + break; + case "type": + b[o] = f[o].toString(); + break; + case "label": + b[o] = f[o]; + break; + default: + b.attr[o] = f[o]; + } + c.edges.push(b); + c.edgesIndex[a.toString()] = b; + return c; + }; + this.dropNode = function(a) { + ((a instanceof Array ? a : [a]) || []).forEach(function(a) { + if (c.nodesIndex[a]) { + var b = null; + c.nodes.some(function(c, f) { + return c.id == a ? ((b = f), !0) : !1; + }); + null != b && c.nodes.splice(b, 1); + delete c.nodesIndex[a]; + c.edges = c.edges.filter(function(b) { + return b.source.id == a + ? (delete c.edgesIndex[b.id], + b.target.degree--, + b.target.inDegree--, + !1) + : b.target.id == a + ? (delete c.edgesIndex[b.id], + b.source.degree--, + b.source.outDegree--, + !1) + : !0; + }); + } else sigma.log('Node "' + a + '" does not exist.'); + }); + return c; + }; + this.dropEdge = function(a) { + ((a instanceof Array ? a : [a]) || []).forEach(function(a) { + if (c.edgesIndex[a]) { + c.edgesIndex[a].source.degree--; + c.edgesIndex[a].source.outDegree--; + c.edgesIndex[a].target.degree--; + c.edgesIndex[a].target.inDegree--; + var b = null; + c.edges.some(function(c, f) { + return c.id == a ? ((b = f), !0) : !1; + }); + null != b && c.edges.splice(b, 1); + delete c.edgesIndex[a]; + } else sigma.log('Edge "' + a + '" does not exist.'); + }); + return c; + }; + this.iterEdges = function(a, b) { + var d = b + ? b.map(function(a) { + return c.edgesIndex[a]; + }) + : c.edges, + f = d.map(j); + f.forEach(a); + d.forEach(function(a, b) { + var d = f[b], + l; + for (l in d) + switch (l) { + case "id": + case "displaySize": + break; + case "weight": + case "size": + a[l] = +d[l]; + break; + case "source": + case "target": + a[l] = c.nodesIndex[l] || a[l]; + break; + case "hidden": + a[l] = !!d[l]; + break; + case "color": + case "label": + case "type": + a[l] = (d[l] || "").toString(); + break; + default: + a.attr[l] = d[l]; + } + }); + return c; + }; + this.iterNodes = function(a, f) { + var d = f + ? f.map(function(a) { + return c.nodesIndex[a]; + }) + : c.nodes, + j = d.map(b); + j.forEach(a); + d.forEach(function(a, b) { + var d = j[b], + c; + for (c in d) + switch (c) { + case "id": + case "attr": + case "degree": + case "inDegree": + case "outDegree": + case "displayX": + case "displayY": + case "displaySize": + break; + case "x": + case "y": + case "size": + a[c] = +d[c]; + break; + case "fixed": + case "active": + case "hidden": + case "forceLabel": + a[c] = !!d[c]; + break; + case "color": + case "label": + a[c] = (d[c] || "").toString(); + break; + default: + a.attr[c] = d[c]; + } + }); + return c; + }; + this.getEdges = function(a) { + var b = ((a instanceof Array ? a : [a]) || []).map(function(a) { + return j(c.edgesIndex[a]); + }); + return a instanceof Array ? b : b[0]; + }; + this.getNodes = function(a) { + var f = ((a instanceof Array ? a : [a]) || []).map(function(a) { + return b(c.nodesIndex[a]); + }); + return a instanceof Array ? f : f[0]; + }; + this.empty = f; + this.rescale = function(a, b, d, f) { + var j = 0, + h = 0; + d && + c.nodes.forEach(function(a) { + h = Math.max(a.size, h); + }); + f && + c.edges.forEach(function(a) { + j = Math.max(a.size, j); + }); + var h = h || 1, + j = j || 1, + g, + l, + s, + t; + d && + c.nodes.forEach(function(a) { + l = Math.max(a.x, l || a.x); + g = Math.min(a.x, g || a.x); + t = Math.max(a.y, t || a.y); + s = Math.min(a.y, s || a.y); + }); + var A = + "outside" == c.p.scalingMode + ? Math.max(a / Math.max(l - g, 1), b / Math.max(t - s, 1)) + : Math.min(a / Math.max(l - g, 1), b / Math.max(t - s, 1)), + i = (c.p.maxNodeSize || h) / A; + l += i; + g -= i; + t += i; + s -= i; + var A = + "outside" == c.p.scalingMode + ? Math.max(a / Math.max(l - g, 1), b / Math.max(t - s, 1)) + : Math.min(a / Math.max(l - g, 1), b / Math.max(t - s, 1)), + u, + k; + !c.p.maxNodeSize && !c.p.minNodeSize + ? ((u = 1), (k = 0)) + : c.p.maxNodeSize == c.p.minNodeSize + ? ((u = 0), (k = c.p.maxNodeSize)) + : ((u = (c.p.maxNodeSize - c.p.minNodeSize) / h), + (k = c.p.minNodeSize)); + var B, E; + !c.p.maxEdgeSize && !c.p.minEdgeSize + ? ((B = 1), (E = 0)) + : ((B = + c.p.maxEdgeSize == c.p.minEdgeSize + ? 0 + : (c.p.maxEdgeSize - c.p.minEdgeSize) / j), + (E = c.p.minEdgeSize)); + d && + c.nodes.forEach(function(c) { + c.displaySize = c.size * u + k; + if (!c.fixed) { + c.displayX = (c.x - (l + g) / 2) * A + a / 2; + c.displayY = (c.y - (t + s) / 2) * A + b / 2; + } + }); + f && + c.edges.forEach(function(a) { + a.displaySize = a.size * B + E; + }); + return c; + }; + this.translate = function(a, b, d, f, j) { + var h = Math.pow(d, c.p.nodesPowRatio); + f && + c.nodes.forEach(function(c) { + c.fixed || + ((c.displayX = c.displayX * d + a), + (c.displayY = c.displayY * d + b)); + c.displaySize *= h; + }); + h = Math.pow(d, c.p.edgesPowRatio); + j && + c.edges.forEach(function(a) { + a.displaySize *= h; + }); + return c; + }; + this.setBorders = function() { + c.borders = {}; + c.nodes.forEach(function(a) { + c.borders.minX = Math.min( + void 0 == c.borders.minX + ? a.displayX - a.displaySize + : c.borders.minX, + a.displayX - a.displaySize + ); + c.borders.maxX = Math.max( + void 0 == c.borders.maxX + ? a.displayX + a.displaySize + : c.borders.maxX, + a.displayX + a.displaySize + ); + c.borders.minY = Math.min( + void 0 == c.borders.minY + ? a.displayY - a.displaySize + : c.borders.minY, + a.displayY - a.displaySize + ); + c.borders.maxY = Math.max( + void 0 == c.borders.maxY + ? a.displayY - a.displaySize + : c.borders.maxY, + a.displayY - a.displaySize + ); + }); + }; + this.checkHover = function(a, b) { + var d, + f, + j, + h = [], + g = []; + c.nodes.forEach(function(c) { + if (c.hidden) c.hover = !1; + else { + d = Math.abs(c.displayX - a); + f = Math.abs(c.displayY - b); + j = c.displaySize; + var s = c.hover, + t = d < j && f < j && Math.sqrt(d * d + f * f) < j; + s && !t + ? ((c.hover = !1), g.push(c.id)) + : t && !s && ((c.hover = !0), h.push(c.id)); + } + }); + h.length && c.dispatch("overnodes", h); + g.length && c.dispatch("outnodes", g); + return c; + }; + } + function q(b, j) { + function f() { + var a; + a = "

    GLOBAL :

    "; + for (var b in c.p.globalProbes) + a += "

    " + b + " : " + c.p.globalProbes[b]() + "

    "; + a += "

    LOCAL :

    "; + for (b in c.p.localProbes) + a += "

    " + b + " : " + c.p.localProbes[b]() + "

    "; + c.p.dom.innerHTML = a; + return c; + } + sigma.classes.Cascade.call(this); + var c = this; + this.instance = b; + this.monitoring = !1; + this.p = { + fps: 40, + dom: j, + globalProbes: { + "Time (ms)": sigma.chronos.getExecutionTime, + Queue: sigma.chronos.getQueuedTasksCount, + Tasks: sigma.chronos.getTasksCount, + FPS: sigma.chronos.getFPS + }, + localProbes: { + "Nodes count": function() { + return c.instance.graph.nodes.length; + }, + "Edges count": function() { + return c.instance.graph.edges.length; + } + } + }; + this.activate = function() { + c.monitoring || (c.monitoring = window.setInterval(f, 1e3 / c.p.fps)); + return c; + }; + this.desactivate = function() { + c.monitoring && + (window.clearInterval(c.monitoring), + (c.monitoring = null), + (c.p.dom.innerHTML = "")); + return c; + }; + } + function g(b) { + var j = b.changedTouches[0], + f = ""; + switch (b.type) { + case "touchstart": + f = "mousedown"; + break; + case "touchmove": + f = "mousemove"; + break; + case "touchend": + f = "mouseup"; + break; + default: + return; + } + var c = document.createEvent("MouseEvent"); + c.initMouseEvent( + f, + !0, + !0, + window, + 1, + j.posX, + j.posY, + j.clientX, + j.clientY, + !1, + !1, + !1, + !1, + 0, + null + ); + j.target.dispatchEvent(c); + b.preventDefault(); + } + function p(b) { + function j(b) { + a.p.mouseEnabled && + (f( + a.mouseX, + a.mouseY, + a.ratio * + (0 < + ((void 0 != b.wheelDelta && b.wheelDelta) || + (void 0 != b.detail && -b.detail)) + ? a.p.zoomMultiply + : 1 / a.p.zoomMultiply) + ), + a.p.blockScroll && + (b.preventDefault ? b.preventDefault() : (b.returnValue = !1))); + } + function f(b, d, f) { + if ( + !a.isMouseDown && + (window.clearInterval(a.interpolationID), + (m = void 0 != f), + (w = a.stageX), + (n = b), + (o = a.stageY), + (l = d), + (h = f || a.ratio), + (h = Math.min(Math.max(h, a.p.minRatio), a.p.maxRatio)), + (u = a.p.directZooming ? 1 - (m ? a.p.zoomDelta : a.p.dragDelta) : 0), + a.ratio != h || a.stageX != n || a.stageY != l) + ) + c(), + (a.interpolationID = window.setInterval(c, 50)), + a.dispatch("startinterpolate"); + } + function c() { + u += m ? a.p.zoomDelta : a.p.dragDelta; + u = Math.min(u, 1); + var b = sigma.easing.quadratic.easeout(u), + c = a.ratio; + a.ratio = c * (1 - b) + h * b; + m + ? ((a.stageX = n + ((a.stageX - n) * a.ratio) / c), + (a.stageY = l + ((a.stageY - l) * a.ratio) / c)) + : ((a.stageX = w * (1 - b) + n * b), (a.stageY = o * (1 - b) + l * b)); + a.dispatch("interpolate"); + 1 <= u && + (window.clearInterval(a.interpolationID), + (b = a.ratio), + m + ? ((a.ratio = h), + (a.stageX = n + ((a.stageX - n) * a.ratio) / b), + (a.stageY = l + ((a.stageY - l) * a.ratio) / b)) + : ((a.stageX = n), (a.stageY = l)), + a.dispatch("stopinterpolate")); + } + sigma.classes.Cascade.call(this); + sigma.classes.EventDispatcher.call(this); + var a = this; + this.p = { + minRatio: 1, + maxRatio: 32, + marginRatio: 1, + zoomDelta: 0.1, + dragDelta: 0.3, + zoomMultiply: 2, + directZooming: !1, + blockScroll: !0, + inertia: 1.1, + mouseEnabled: !0, + touchEnabled: !0 + }; + var i = 0, + d = 0, + w = 0, + o = 0, + h = 1, + n = 0, + l = 0, + s = 0, + t = 0, + A = 0, + k = 0, + u = 0, + m = !1; + this.stageY = this.stageX = 0; + this.ratio = 1; + this.mouseY = this.mouseX = 0; + this.isTouchDown = this.isMouseDown = !1; + b.addEventListener("DOMMouseScroll", j, !0); + b.addEventListener("mousewheel", j, !0); + b.addEventListener( + "mousemove", + function(b) { + a.mouseX = + (void 0 != b.offsetX && b.offsetX) || + (void 0 != b.layerX && b.layerX) || + (void 0 != b.clientX && b.clientX); + a.mouseY = + (void 0 != b.offsetY && b.offsetY) || + (void 0 != b.layerY && b.layerY) || + (void 0 != b.clientY && b.clientY); + if (a.isMouseDown) { + var c = a.mouseX - i + w, + h = a.mouseY - d + o; + if (c != a.stageX || h != a.stageY) + (t = s), + (k = A), + (s = c), + (A = h), + (a.stageX = c), + (a.stageY = h), + a.dispatch("drag"); + } + a.dispatch("move"); + b.preventDefault ? b.preventDefault() : (b.returnValue = !1); + }, + !0 + ); + b.addEventListener( + "mousedown", + function(b) { + a.p.mouseEnabled && + ((a.isMouseDown = !0), + a.dispatch("mousedown"), + (w = a.stageX), + (o = a.stageY), + (i = a.mouseX), + (d = a.mouseY), + (t = s = a.stageX), + (k = A = a.stageY), + a.dispatch("startdrag"), + b.preventDefault ? b.preventDefault() : (b.returnValue = !1)); + }, + !0 + ); + document.addEventListener( + "mouseup", + function(b) { + a.p.mouseEnabled && + a.isMouseDown && + ((a.isMouseDown = !1), + a.dispatch("mouseup"), + (w != a.stageX || o != a.stageY) && + f( + a.stageX + a.p.inertia * (a.stageX - t), + a.stageY + a.p.inertia * (a.stageY - k) + ), + b.preventDefault ? b.preventDefault() : (b.returnValue = !1)); + }, + !0 + ); + b.addEventListener("touchstart", g, !0); + b.addEventListener("touchmove", g, !0); + document.addEventListener("touchend", g, !0); + b.addEventListener("touchcancel", g, !0); + this.checkBorders = function() { + return a; + }; + this.interpolate = f; + } + function z(b, j, f, c, a, g, d) { + function i(a) { + var b = c, + d = + "fixed" == h.p.labelSize + ? h.p.defaultLabelSize + : h.p.labelSizeRatio * a.displaySize; + b.font = + (h.p.hoverFontStyle || h.p.fontStyle || "") + + " " + + d + + "px " + + (h.p.hoverFont || h.p.font || ""); + b.fillStyle = + "node" == h.p.labelHoverBGColor + ? a.color || h.p.defaultNodeColor + : h.p.defaultHoverLabelBGColor; + b.beginPath(); + h.p.labelHoverShadow && + ((b.shadowOffsetX = 0), + (b.shadowOffsetY = 0), + (b.shadowBlur = 4), + (b.shadowColor = h.p.labelHoverShadowColor)); + sigma.tools.drawRoundRect( + b, + Math.round(a.displayX - d / 2 - 2), + Math.round(a.displayY - d / 2 - 2), + Math.round( + b.measureText(a.label).width + 1.5 * a.displaySize + d / 2 + 4 + ), + Math.round(d + 4), + Math.round(d / 2 + 2), + "left" + ); + b.closePath(); + b.fill(); + b.shadowOffsetX = 0; + b.shadowOffsetY = 0; + b.shadowBlur = 0; + b.beginPath(); + b.fillStyle = + "node" == h.p.nodeBorderColor + ? a.color || h.p.defaultNodeColor + : h.p.defaultNodeBorderColor; + b.arc( + Math.round(a.displayX), + Math.round(a.displayY), + a.displaySize + h.p.borderSize, + 0, + 2 * Math.PI, + !0 + ); + b.closePath(); + b.fill(); + b.beginPath(); + b.fillStyle = + "node" == h.p.nodeHoverColor + ? a.color || h.p.defaultNodeColor + : h.p.defaultNodeHoverColor; + b.arc( + Math.round(a.displayX), + Math.round(a.displayY), + a.displaySize, + 0, + 2 * Math.PI, + !0 + ); + b.closePath(); + b.fill(); + b.fillStyle = + "node" == h.p.labelHoverColor + ? a.color || h.p.defaultNodeColor + : h.p.defaultLabelHoverColor; + b.fillText( + a.label, + Math.round(a.displayX + 1.5 * a.displaySize), + Math.round(a.displayY + d / 2 - 3) + ); + return h; + } + function o(a) { + if (isNaN(a.x) || isNaN(a.y)) + throw Error("A node's coordinate is not a number (id: " + a.id + ")"); + return ( + !a.hidden && + a.displayX + a.displaySize > -n / 3 && + a.displayX - a.displaySize < (4 * n) / 3 && + a.displayY + a.displaySize > -l / 3 && + a.displayY - a.displaySize < (4 * l) / 3 + ); + } + sigma.classes.Cascade.call(this); + var h = this; + this.p = { + labelColor: "default", + defaultLabelColor: "#000", + labelHoverBGColor: "default", + defaultHoverLabelBGColor: "#fff", + labelHoverShadow: !0, + labelHoverShadowColor: "#000", + labelHoverColor: "default", + defaultLabelHoverColor: "#000", + labelActiveBGColor: "default", + defaultActiveLabelBGColor: "#fff", + labelActiveShadow: !0, + labelActiveShadowColor: "#000", + labelActiveColor: "default", + defaultLabelActiveColor: "#000", + labelSize: "fixed", + defaultLabelSize: 12, + labelSizeRatio: 2, + labelThreshold: 6, + font: "Arial", + hoverFont: "", + activeFont: "", + fontStyle: "", + hoverFontStyle: "", + activeFontStyle: "", + edgeColor: "source", + defaultEdgeColor: "#aaa", + defaultEdgeType: "line", + defaultNodeColor: "#aaa", + nodeHoverColor: "node", + defaultNodeHoverColor: "#fff", + nodeActiveColor: "node", + defaultNodeActiveColor: "#fff", + borderSize: 0, + nodeBorderColor: "node", + defaultNodeBorderColor: "#fff", + edgesSpeed: 200, + nodesSpeed: 200, + labelsSpeed: 200 + }; + var n = g, + l = d; + this.currentLabelIndex = this.currentNodeIndex = this.currentEdgeIndex = 0; + this.task_drawLabel = function() { + for ( + var b = a.nodes.length, c = 0; + c++ < h.p.labelsSpeed && h.currentLabelIndex < b; + + ) + if (h.isOnScreen(a.nodes[h.currentLabelIndex])) { + var d = a.nodes[h.currentLabelIndex++], + j = f; + if (d.displaySize >= h.p.labelThreshold || d.forceLabel) { + var g = + "fixed" == h.p.labelSize + ? h.p.defaultLabelSize + : h.p.labelSizeRatio * d.displaySize; + j.font = h.p.fontStyle + g + "px " + h.p.font; + j.fillStyle = + "node" == h.p.labelColor + ? d.color || h.p.defaultNodeColor + : h.p.defaultLabelColor; + j.fillText( + d.label, + Math.round(d.displayX + 1.5 * d.displaySize), + Math.round(d.displayY + g / 2 - 3) + ); + } + } else h.currentLabelIndex++; + return h.currentLabelIndex < b; + }; + this.task_drawEdge = function() { + for ( + var b = a.edges.length, c, d, f = 0; + f++ < h.p.edgesSpeed && h.currentEdgeIndex < b; + + ) + if ( + ((e = a.edges[h.currentEdgeIndex]), + (c = e.source), + (d = e.target), + e.hidden || + c.hidden || + d.hidden || + (!h.isOnScreen(c) && !h.isOnScreen(d))) + ) + h.currentEdgeIndex++; + else { + c = a.edges[h.currentEdgeIndex++]; + d = c.source.displayX; + var g = c.source.displayY, + o = c.target.displayX, + i = c.target.displayY, + l = c.color; + if (!l) + switch (h.p.edgeColor) { + case "source": + l = c.source.color || h.p.defaultNodeColor; + break; + case "target": + l = c.target.color || h.p.defaultNodeColor; + break; + default: + l = h.p.defaultEdgeColor; + } + var n = j; + switch (c.type || h.p.defaultEdgeType) { + case "curve": + n.strokeStyle = l; + n.lineWidth = c.displaySize / 3; + n.beginPath(); + n.moveTo(d, g); + n.quadraticCurveTo( + (d + o) / 2 + (i - g) / 4, + (g + i) / 2 + (d - o) / 4, + o, + i + ); + n.stroke(); + break; + default: + (n.strokeStyle = l), + (n.lineWidth = c.displaySize / 3), + n.beginPath(), + n.moveTo(d, g), + n.lineTo(o, i), + n.stroke(); + } + } + return h.currentEdgeIndex < b; + }; + this.task_drawNode = function() { + for ( + var c = a.nodes.length, d = 0; + d++ < h.p.nodesSpeed && h.currentNodeIndex < c; + + ) + if (h.isOnScreen(a.nodes[h.currentNodeIndex])) { + var f = a.nodes[h.currentNodeIndex++], + j = Math.round(10 * f.displaySize) / 10, + g = b; + ctx = b; + node = f; + + // AS 20190621 add node border + // if (h.p.defaultBorderView==="always" || + // (h.p.defaultBorderView==="node" && + if (node.attr['drawBorder']) { + ctx.beginPath(); + if (node.attr['grey']) { + ctx.fillStyle = "rgba(0,0,0,0.1)" ; + } + //h.p.nodeBorderColor == 'node' ? + // (node['color'] || h.p.defaultNodeColor) : + // h.p.defaultNodeBorderColor; + + g.arc(f.displayX, f.displayY, j+ h.p.borderSize, 0, 2 * Math.PI, !0); + ctx.closePath(); + ctx.fill(); + + + } + g.fillStyle = f.color; + if (node.attr['grey']) { + ctx.fillStyle = "rgba(244,244,244,0.1)" ; + } + g.beginPath(); + g.arc(f.displayX, f.displayY, j, 0, 2 * Math.PI, !0); + g.closePath(); + g.fill(); + f.hover && i(f); + } else { + // not on screen, don't render + h.currentNodeIndex++; + } + + + + return h.currentNodeIndex < c; + }; + this.drawActiveNode = function(a) { + var b = c; + if (!o(a)) return h; + var d = + "fixed" == h.p.labelSize + ? h.p.defaultLabelSize + : h.p.labelSizeRatio * a.displaySize; + b.font = + (h.p.activeFontStyle || h.p.fontStyle || "") + + " " + + d + + "px " + + (h.p.activeFont || h.p.font || ""); + b.fillStyle = + "node" == h.p.labelHoverBGColor + ? a.color || h.p.defaultNodeColor + : h.p.defaultActiveLabelBGColor; + b.beginPath(); + h.p.labelActiveShadow && + ((b.shadowOffsetX = 0), + (b.shadowOffsetY = 0), + (b.shadowBlur = 4), + (b.shadowColor = h.p.labelActiveShadowColor)); + sigma.tools.drawRoundRect( + b, + Math.round(a.displayX - d / 2 - 2), + Math.round(a.displayY - d / 2 - 2), + Math.round( + b.measureText(a.label).width + 1.5 * a.displaySize + d / 2 + 4 + ), + Math.round(d + 4), + Math.round(d / 2 + 2), + "left" + ); + b.closePath(); + b.fill(); + b.shadowOffsetX = 0; + b.shadowOffsetY = 0; + b.shadowBlur = 0; + b.beginPath(); + b.fillStyle = + "node" == h.p.nodeBorderColor + ? a.color || h.p.defaultNodeColor + : h.p.defaultNodeBorderColor; + b.arc( + Math.round(a.displayX), + Math.round(a.displayY), + a.displaySize + h.p.borderSize, + 0, + 2 * Math.PI, + !0 + ); + b.closePath(); + b.fill(); + b.beginPath(); + b.fillStyle = + "node" == h.p.nodeActiveColor + ? a.color || h.p.defaultNodeColor + : h.p.defaultNodeActiveColor; + b.arc( + Math.round(a.displayX), + Math.round(a.displayY), + a.displaySize, + 0, + 2 * Math.PI, + !0 + ); + b.closePath(); + b.fill(); + b.fillStyle = + "node" == h.p.labelActiveColor + ? a.color || h.p.defaultNodeColor + : h.p.defaultLabelActiveColor; + b.fillText( + a.label, + Math.round(a.displayX + 1.5 * a.displaySize), + Math.round(a.displayY + d / 2 - 3) + ); + return h; + }; + this.drawHoverNode = i; + this.isOnScreen = o; + this.resize = function(a, b) { + n = a; + l = b; + return h; + }; + } + function F(b, g) { + function f() { + sigma.chronos + .removeTask("node_" + d.id, 2) + .removeTask("edge_" + d.id, 2) + .removeTask("label_" + d.id, 2) + .stopTasks(); + return d; + } + function c(a, b) { + d.domElements[a] = document.createElement(b); + d.domElements[a].style.position = "absolute"; + d.domElements[a].setAttribute("id", "sigma_" + a + "_" + d.id); + d.domElements[a].setAttribute("class", "sigma_" + a + "_" + b); + d.domElements[a].setAttribute("width", d.width + "px"); + d.domElements[a].setAttribute("height", d.height + "px"); + d.domRoot.appendChild(d.domElements[a]); + return d; + } + function a() { + d.p.drawHoverNodes && + (d.graph.checkHover(d.mousecaptor.mouseX, d.mousecaptor.mouseY), + d.graph.nodes.forEach(function(a) { + a.hover && !a.active && d.plotter.drawHoverNode(a); + })); + return d; + } + function D() { + d.p.drawActiveNodes && + d.graph.nodes.forEach(function(a) { + a.active && d.plotter.drawActiveNode(a); + }); + return d; + } + sigma.classes.Cascade.call(this); + sigma.classes.EventDispatcher.call(this); + var d = this; + this.id = g.toString(); + this.p = { + auto: !0, + drawNodes: 2, + drawEdges: 1, + drawLabels: 2, + lastNodes: 2, + lastEdges: 0, + lastLabels: 2, + drawHoverNodes: !0, + drawActiveNodes: !0 + }; + this.domRoot = b; + this.width = this.domRoot.offsetWidth; + this.height = this.domRoot.offsetHeight; + this.graph = new i(); + this.domElements = {}; + c("edges", "canvas"); + c("nodes", "canvas"); + c("labels", "canvas"); + c("hover", "canvas"); + c("monitor", "div"); + c("mouse", "canvas"); + this.plotter = new z( + this.domElements.nodes.getContext("2d"), + this.domElements.edges.getContext("2d"), + this.domElements.labels.getContext("2d"), + this.domElements.hover.getContext("2d"), + this.graph, + this.width, + this.height + ); + this.monitor = new q(this, this.domElements.monitor); + this.mousecaptor = new p(this.domElements.mouse, this.id); + this.mousecaptor + .bind("drag interpolate", function() { + d.draw( + d.p.auto ? 2 : d.p.drawNodes, + d.p.auto ? 0 : d.p.drawEdges, + d.p.auto ? 2 : d.p.drawLabels, + !0 + ); + }) + .bind("stopdrag stopinterpolate", function() { + d.draw( + d.p.auto ? 2 : d.p.drawNodes, + d.p.auto ? 1 : d.p.drawEdges, + d.p.auto ? 2 : d.p.drawLabels, + !0 + ); + }) + .bind("mousedown mouseup", function(a) { + var b = d.graph.nodes + .filter(function(a) { + return !!a.hover; + }) + .map(function(a) { + return a.id; + }); + d.dispatch("mousedown" == a.type ? "downgraph" : "upgraph"); + b.length && + d.dispatch("mousedown" == a.type ? "downnodes" : "upnodes", b); + }) + .bind("move", function() { + d.domElements.hover + .getContext("2d") + .clearRect( + 0, + 0, + d.domElements.hover.width, + d.domElements.hover.height + ); + a(); + D(); + }); + sigma.chronos + .bind("startgenerators", function() { + sigma.chronos.getGeneratorsIDs().some(function(a) { + return !!a.match(RegExp("_ext_" + d.id + "$", "")); + }) && + d.draw( + d.p.auto ? 2 : d.p.drawNodes, + d.p.auto ? 0 : d.p.drawEdges, + d.p.auto ? 2 : d.p.drawLabels + ); + }) + .bind("stopgenerators", function() { + d.draw(); + }); + for (var w = 0; w < m.plugins.length; w++) m.plugins[w](this); + this.draw = function(a, b, c, g) { + if ( + g && + sigma.chronos.getGeneratorsIDs().some(function(a) { + return !!a.match(RegExp("_ext_" + d.id + "$", "")); + }) + ) + return d; + a = void 0 == a ? d.p.drawNodes : a; + b = void 0 == b ? d.p.drawEdges : b; + c = void 0 == c ? d.p.drawLabels : c; + g = { nodes: a, edges: b, labels: c }; + d.p.lastNodes = a; + d.p.lastEdges = b; + d.p.lastLabels = c; + f(); + d.graph.rescale(d.width, d.height, 0 < a, 0 < b).setBorders(); + d.mousecaptor.checkBorders(d.graph.borders, d.width, d.height); + d.graph.translate( + d.mousecaptor.stageX, + d.mousecaptor.stageY, + d.mousecaptor.ratio, + 0 < a, + 0 < b + ); + d.dispatch("graphscaled"); + for (var j in d.domElements) + "canvas" == d.domElements[j].nodeName.toLowerCase() && + (void 0 == g[j] || 0 <= g[j]) && + d.domElements[j] + .getContext("2d") + .clearRect(0, 0, d.domElements[j].width, d.domElements[j].height); + d.plotter.currentEdgeIndex = 0; + d.plotter.currentNodeIndex = 0; + d.plotter.currentLabelIndex = 0; + j = null; + g = !1; + if (a) + if (1 < a) for (; d.plotter.task_drawNode(); ); + else + sigma.chronos.addTask(d.plotter.task_drawNode, "node_" + d.id, !1), + (g = !0), + (j = "node_" + d.id); + if (c) + if (1 < c) for (; d.plotter.task_drawLabel(); ); + else + j + ? sigma.chronos.queueTask( + d.plotter.task_drawLabel, + "label_" + d.id, + j + ) + : sigma.chronos.addTask( + d.plotter.task_drawLabel, + "label_" + d.id, + !1 + ), + (g = !0), + (j = "label_" + d.id); + if (b) + if (1 < b) for (; d.plotter.task_drawEdge(); ); + else + j + ? sigma.chronos.queueTask( + d.plotter.task_drawEdge, + "edge_" + d.id, + j + ) + : sigma.chronos.addTask( + d.plotter.task_drawEdge, + "edge_" + d.id, + !1 + ), + (g = !0), + (j = "edge_" + d.id); + d.dispatch("draw"); + d.refresh(); + g && sigma.chronos.runTasks(); + return d; + }; + this.resize = function(a, b) { + var c = d.width, + f = d.height; + void 0 != a && void 0 != b + ? ((d.width = a), (d.height = b)) + : ((d.width = d.domRoot.offsetWidth), + (d.height = d.domRoot.offsetHeight)); + if (c != d.width || f != d.height) { + for (var j in d.domElements) + d.domElements[j].setAttribute("width", d.width + "px"), + d.domElements[j].setAttribute("height", d.height + "px"); + d.plotter.resize(d.width, d.height); + d.draw(d.p.lastNodes, d.p.lastEdges, d.p.lastLabels, !0); + } + return d; + }; + this.refresh = function() { + d.domElements.hover + .getContext("2d") + .clearRect(0, 0, d.domElements.hover.width, d.domElements.hover.height); + a(); + D(); + return d; + }; + this.drawHover = a; + this.drawActive = D; + this.clearSchedule = f; + window.addEventListener("resize", function() { + d.resize(); + }); + } + function x(b) { + var j = this; + sigma.classes.EventDispatcher.call(this); + this._core = b; + this.kill = function() {}; + this.getID = function() { + return b.id; + }; + this.configProperties = function(f, c) { + var a = b.config(f, c); + return a == b ? j : a; + }; + this.drawingProperties = function(f, c) { + var a = b.plotter.config(f, c); + return a == b.plotter ? j : a; + }; + this.mouseProperties = function(f, c) { + var a = b.mousecaptor.config(f, c); + return a == b.mousecaptor ? j : a; + }; + this.graphProperties = function(f, c) { + var a = b.graph.config(f, c); + return a == b.graph ? j : a; + }; + this.getMouse = function() { + return { + mouseX: b.mousecaptor.mouseX, + mouseY: b.mousecaptor.mouseY, + down: b.mousecaptor.isMouseDown + }; + }; + this.position = function(f, c, a) { + if (0 == arguments.length) + return { + stageX: b.mousecaptor.stageX, + stageY: b.mousecaptor.stageY, + ratio: b.mousecaptor.ratio + }; + b.mousecaptor.stageX = void 0 != f ? f : b.mousecaptor.stageX; + b.mousecaptor.stageY = void 0 != c ? c : b.mousecaptor.stageY; + b.mousecaptor.ratio = void 0 != a ? a : b.mousecaptor.ratio; + return j; + }; + this.goTo = function(f, c, a) { + b.mousecaptor.interpolate(f, c, a); + return j; + }; + this.zoomTo = function(f, c, a) { + a = Math.min( + Math.max(b.mousecaptor.config("minRatio"), a), + b.mousecaptor.config("maxRatio") + ); + a == b.mousecaptor.ratio + ? b.mousecaptor.interpolate( + f - b.width / 2 + b.mousecaptor.stageX, + c - b.height / 2 + b.mousecaptor.stageY + ) + : b.mousecaptor.interpolate( + (a * f - (b.mousecaptor.ratio * b.width) / 2) / + (a - b.mousecaptor.ratio), + (a * c - (b.mousecaptor.ratio * b.height) / 2) / + (a - b.mousecaptor.ratio), + a + ); + return j; + }; + this.resize = function(f, c) { + b.resize(f, c); + return j; + }; + this.draw = function(f, c, a, g) { + b.draw(f, c, a, g); + return j; + }; + this.refresh = function() { + b.refresh(); + return j; + }; + this.addGenerator = function(f, c, a) { + sigma.chronos.addGenerator(f + "_ext_" + b.id, c, a); + return j; + }; + this.removeGenerator = function(f) { + sigma.chronos.removeGenerator(f + "_ext_" + b.id); + return j; + }; + this.addNode = function(f, c) { + b.graph.addNode(f, c); + return j; + }; + this.addEdge = function(f, c, a, g) { + b.graph.addEdge(f, c, a, g); + return j; + }; + this.dropNode = function(f) { + b.graph.dropNode(f); + return j; + }; + this.dropEdge = function(f) { + b.graph.dropEdge(f); + return j; + }; + this.pushGraph = function(f, c) { + f.nodes && + f.nodes.forEach(function(a) { + a.id && (!c || !b.graph.nodesIndex[a.id]) && j.addNode(a.id, a); + }); + f.edges && + f.edges.forEach(function(a) { + (validID = a.source && a.target && a.id) && + (!c || !b.graph.edgesIndex[a.id]) && + j.addNode(a.id, a.source, a.target, a); + }); + return j; + }; + this.emptyGraph = function() { + b.graph.empty(); + return j; + }; + this.getNodesCount = function() { + return b.graph.nodes.length; + }; + this.getEdgesCount = function() { + return b.graph.edges.length; + }; + this.iterNodes = function(f, c) { + b.graph.iterNodes(f, c); + return j; + }; + this.iterEdges = function(f, c) { + b.graph.iterEdges(f, c); + return j; + }; + this.getNodes = function(f) { + return b.graph.getNodes(f); + }; + this.getEdges = function(f) { + return b.graph.getEdges(f); + }; + this.activateMonitoring = function() { + return b.monitor.activate(); + }; + this.desactivateMonitoring = function() { + return b.monitor.desactivate(); + }; + b.bind("downnodes upnodes downgraph upgraph", function(b) { + j.dispatch(b.type, b.content); + }); + b.graph.bind("overnodes outnodes", function(b) { + j.dispatch(b.type, b.content); + }); + } + var k = 0, + m = { plugins: [] }; + sigma.init = function(b) { + b = new F(b, (++k).toString()); + sigma.instances[k] = new x(b); + return sigma.instances[k]; + }; + sigma.addPlugin = function(b, g, f) { + x.prototype[b] = g; + m.plugins.push(f); + }; + sigma.chronos = new (function() { + function b(a) { + window.setTimeout(a, 0); + return h; + } + function g() { + for (h.dispatch("frameinserted"); n && v.length && f(); ); + !n || !v.length + ? a() + : ((B = new Date().getTime()), + m++, + (z = u - p), + (q = p - z), + h.dispatch("insertframe"), + b(g)); + } + function f() { + C %= v.length; + if (!v[C].task()) { + var a = v[C].taskName; + y = y.filter(function(b) { + b.taskParent == a && v.push({ taskName: b.taskName, task: b.task }); + return b.taskParent != a; + }); + h.dispatch("killed", v.splice(C--, 1)[0]); + } + C++; + u = new Date().getTime() - B; + return u <= q; + } + function c() { + n = !0; + m = C = 0; + x = B = new Date().getTime(); + h.dispatch("start"); + h.dispatch("insertframe"); + b(g); + return h; + } + function a() { + h.dispatch("stop"); + n = !1; + return h; + } + function i(a, b, d) { + if ("function" != typeof a) + throw Error('Task "' + b + '" is not a function'); + v.push({ taskName: b, task: a }); + n = !(!n && !((d && c()) || 1)); + return h; + } + function d(a) { + return a + ? Object.keys(r).filter(function(a) { + return !!r[a].on; + }).length + : Object.keys(r).length; + } + function w() { + Object.keys(r).length + ? (h.dispatch("startgenerators"), + h.unbind("killed", o), + b(function() { + for (var a in r) (r[a].on = !0), i(r[a].task, a, !1); + }), + h.bind("killed", o).runTasks()) + : h.dispatch("stopgenerators"); + return h; + } + function o(a) { + void 0 != r[a.content.taskName] && + (r[a.content.taskName].del || !r[a.content.taskName].condition() + ? delete r[a.content.taskName] + : (r[a.content.taskName].on = !1), + 0 == d(!0) && w()); + } + sigma.classes.EventDispatcher.call(this); + var h = this, + n = !1, + l = 80, + k = 0, + m = 0, + p = 1e3 / l, + q = p, + u = 0, + x = 0, + B = 0, + z = 0, + r = {}, + v = [], + y = [], + C = 0; + this.frequency = function(a) { + return void 0 != a + ? ((l = Math.abs(1 * a)), (p = 1e3 / l), (m = 0), h) + : l; + }; + this.runTasks = c; + this.stopTasks = a; + this.insertFrame = b; + this.addTask = i; + this.queueTask = function(a, b, c) { + if ("function" != typeof a) + throw Error('Task "' + b + '" is not a function'); + if ( + !v.concat(y).some(function(a) { + return a.taskName == c; + }) + ) + throw Error('Parent task "' + c + '" of "' + b + '" is not attached.'); + y.push({ taskParent: c, taskName: b, task: a }); + return h; + }; + this.removeTask = function(b, c) { + if (void 0 == b) + (v = []), 1 == c ? (y = []) : 2 == c && ((v = y), (y = [])), a(); + else { + var d = "string" == typeof b ? b : ""; + v = v.filter(function(a) { + return ("string" == typeof b + ? a.taskName == b + : a.task == b) + ? ((d = a.taskName), !1) + : !0; + }); + 0 < c && + (y = y.filter(function(a) { + 1 == c && a.taskParent == d && v.push(a); + return a.taskParent != d; + })); + } + n = !(v.length && (!a() || 1)); + return h; + }; + this.addGenerator = function(a, b, c) { + if (void 0 != r[a]) return h; + r[a] = { task: b, condition: c }; + 0 == d(!0) && w(); + return h; + }; + this.removeGenerator = function(a) { + r[a] && ((r[a].on = !1), (r[a].del = !0)); + return h; + }; + this.startGenerators = w; + this.getGeneratorsIDs = function() { + return Object.keys(r); + }; + this.getFPS = function() { + n && (k = Math.round(1e4 * (m / (new Date().getTime() - x))) / 10); + return k; + }; + this.getTasksCount = function() { + return v.length; + }; + this.getQueuedTasksCount = function() { + return y.length; + }; + this.getExecutionTime = function() { + return B - x; + }; + return this; + })(); + sigma.debugMode = 0; + sigma.log = function() { + if (1 == sigma.debugMode) + for (var b in arguments) console.log(arguments[b]); + else if (1 < sigma.debugMode) + for (b in arguments) throw Error(arguments[b]); + return sigma; + }; + sigma.easing = { linear: {}, quadratic: {} }; + sigma.easing.linear.easenone = function(b) { + return b; + }; + sigma.easing.quadratic.easein = function(b) { + return b * b; + }; + sigma.easing.quadratic.easeout = function(b) { + return -b * (b - 2); + }; + sigma.easing.quadratic.easeinout = function(b) { + return 1 > (b *= 2) ? 0.5 * b * b : -0.5 * (--b * (b - 2) - 1); + }; + sigma.tools.drawRoundRect = function(b, g, f, c, a, i, d) { + var i = i ? i : 0, + k = d ? d : [], + k = "string" == typeof k ? k.split(" ") : k, + d = + i && + (0 <= k.indexOf("topleft") || + 0 <= k.indexOf("top") || + 0 <= k.indexOf("left")), + m = + i && + (0 <= k.indexOf("topright") || + 0 <= k.indexOf("top") || + 0 <= k.indexOf("right")), + h = + i && + (0 <= k.indexOf("bottomleft") || + 0 <= k.indexOf("bottom") || + 0 <= k.indexOf("left")), + k = + i && + (0 <= k.indexOf("bottomright") || + 0 <= k.indexOf("bottom") || + 0 <= k.indexOf("right")); + b.moveTo(g, f + i); + d ? b.arcTo(g, f, g + i, f, i) : b.lineTo(g, f); + m + ? (b.lineTo(g + c - i, f), b.arcTo(g + c, f, g + c, f + i, i)) + : b.lineTo(g + c, f); + k + ? (b.lineTo(g + c, f + a - i), b.arcTo(g + c, f + a, g + c - i, f + a, i)) + : b.lineTo(g + c, f + a); + h + ? (b.lineTo(g + i, f + a), b.arcTo(g, f + a, g, f + a - i, i)) + : b.lineTo(g, f + a); + b.lineTo(g, f + i); + }; + sigma.tools.getRGB = function(b, g) { + var b = b.toString(), + f = { r: 0, g: 0, b: 0 }; + if (3 <= b.length && "#" == b.charAt(0)) { + var c = b.length - 1; + 6 == c + ? (f = { + r: parseInt(b.charAt(1) + b.charAt(2), 16), + g: parseInt(b.charAt(3) + b.charAt(4), 16), + b: parseInt(b.charAt(5) + b.charAt(5), 16) + }) + : 3 == c && + (f = { + r: parseInt(b.charAt(1) + b.charAt(1), 16), + g: parseInt(b.charAt(2) + b.charAt(2), 16), + b: parseInt(b.charAt(3) + b.charAt(3), 16) + }); + } + g && (f = [f.r, f.g, f.b]); + return f; + }; + sigma.tools.rgbToHex = function(b, g, f) { + return sigma.tools.toHex(b) + sigma.tools.toHex(g) + sigma.tools.toHex(f); + }; + sigma.tools.toHex = function(b) { + b = parseInt(b, 10); + if (isNaN(b)) return "00"; + b = Math.max(0, Math.min(b, 255)); + return ( + "0123456789ABCDEF".charAt((b - (b % 16)) / 16) + + "0123456789ABCDEF".charAt(b % 16) + ); + }; + sigma.publicPrototype = x.prototype; +})(); diff --git a/html/observatory/js/sigma/sigma.parseGexf.js b/html/observatory/js/sigma/sigma.parseGexf.js new file mode 100644 index 0000000..1924c3e --- /dev/null +++ b/html/observatory/js/sigma/sigma.parseGexf.js @@ -0,0 +1,166 @@ +// Mathieu Jacomy @ Sciences Po Mdialab & WebAtlas +// (requires sigma.js to be loaded) +sigma.publicPrototype.parseGexf = function(gexfPath,callback) { + // Load XML file: + var gexfhttp, gexf; + var sigmaInstance = this; + gexfhttp = window.XMLHttpRequest ? + new XMLHttpRequest() : + new ActiveXObject('Microsoft.XMLHTTP'); + + gexfhttp.overrideMimeType('text/xml'); + gexfhttp.open('GET', gexfPath, false); + gexfhttp.send(); + gexf = gexfhttp.responseXML; + + var viz='http://www.gexf.net/1.2draft/viz'; // Vis namespace + var i, j, k; + + // Parse Attributes + // This is confusing, so I'll comment heavily + var nodesAttributes = []; // The list of attributes of the nodes of the graph that we build in json + var nodesAttributesDict = {}; + var edgesAttributes = []; // The list of attributes of the edges of the graph that we build in json + var edgesAttributesDict = {}; + var attributesNodes = gexf.getElementsByTagName('attributes'); // In the gexf (that is an xml), the list of xml nodes 'attributes' (note the plural 's') + + for(i = 0; i0){ + sizeNode = sizeNodes[0]; + size = parseFloat(sizeNode.getAttribute('value')); + } + + var positionNodes = nodeNode.getElementsByTagName('position'); + positionNodes = positionNodes.length ? + positionNodes : + nodeNode.getElementsByTagNameNS('*','position'); + if(positionNodes.length>0){ + var positionNode = positionNodes[0]; + x = parseFloat(positionNode.getAttribute('x')); + y = parseFloat(positionNode.getAttribute('y')); + } + + var colorNodes = nodeNode.getElementsByTagName('color'); + colorNodes = colorNodes.length ? + colorNodes : + nodeNode.getElementsByTagNameNS('*','color'); + if(colorNodes.length>0){ + colorNode = colorNodes[0]; + color = '#'+sigma.tools.rgbToHex(parseFloat(colorNode.getAttribute('r')), + parseFloat(colorNode.getAttribute('g')), + parseFloat(colorNode.getAttribute('b'))); + } + + // Create Node + var node = {label:label, size:size, x:x, y:y, attributes:{}, color:color}; // The graph node + + // Attribute values + var attvalueNodes = nodeNode.getElementsByTagName('attvalue'); + for(k=0; k + + + Observatory + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + + +
    +
    +

    User pathways across .gov.au

    +

    This diagram shows the pathways created by people as they move between .gov.au webpages. Each circle + represents a webpage and each line is a link between those pages
    + Select a website from the Agency websites list to better understand how people are coming to + those webpages, and where they are going to after they visit.
    +

    +
    + +
    +
    +
    +
    + + + + + +
    +
    +
    +
    +
    +
    + + + + diff --git a/html/observatory/observatory-html.code-workspace b/html/observatory/observatory-html.code-workspace new file mode 100644 index 0000000..876a149 --- /dev/null +++ b/html/observatory/observatory-html.code-workspace @@ -0,0 +1,8 @@ +{ + "folders": [ + { + "path": "." + } + ], + "settings": {} +} \ No newline at end of file diff --git a/html/observatory/run.py b/html/observatory/run.py new file mode 100644 index 0000000..e24f57e --- /dev/null +++ b/html/observatory/run.py @@ -0,0 +1,36 @@ +#!/usr/bin/python3 +# https://stackoverflow.com/questions/14088294/multithreaded-web-server-in-python +try: + # Python3 + import http.server as SimpleHTTPServer + import http.server as BaseHTTPServer + import socketserver as SocketServer +except ImportError: + # Python 2 + import SimpleHTTPServer + import BaseHTTPServer + import SocketServer + +import sys +import os + +# The absolute path of the directoy for this file: +_ROOT = os.path.abspath(os.path.dirname(__file__)) + +class ThreadingSimpleServer(SocketServer.ThreadingMixIn,BaseHTTPServer.HTTPServer): + pass + +if sys.argv[1:]: + port = int(sys.argv[1]) +else: + port = 8000 + +server = ThreadingSimpleServer(('', port), SimpleHTTPServer.SimpleHTTPRequestHandler) +print("Serving HTTP on 0.0.0.0 port",port,"...") + +try: + while 1: + sys.stdout.flush() + server.handle_request() +except KeyboardInterrupt: + print("Finished") \ No newline at end of file diff --git a/html/observatory/run.sh b/html/observatory/run.sh new file mode 100644 index 0000000..df87b1b --- /dev/null +++ b/html/observatory/run.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +brew install npm +npm install -g browser-sync +browser-sync -s -w . \ No newline at end of file diff --git a/html/observatory/server/gexf2Json.py b/html/observatory/server/gexf2Json.py new file mode 100644 index 0000000..187816c --- /dev/null +++ b/html/observatory/server/gexf2Json.py @@ -0,0 +1,165 @@ +import pprint +import xml.dom.minidom +from xml.dom.minidom import Node +import sys +from optparse import OptionParser +import json +import random + +usage="Run as python gexf2json.py input.gexf output.json [pretty]" + +"""parser = OptionParser() +parser.add_option("-i", "--input", dest="input", + help="gexf file to read as input", metavar="INPUT") +parser.add_option("-o", "--output", dest="output", + help="json file to write to as output", metavar="OUTPUT") +parser.add_option("-q", "--quiet", + action="store_false", dest="verbose", default=True, + help="don't print status messages to stdout") + +(options, args) = parser.parse_args() +""" + +if (len(sys.argv)<3): + print usage + exit() + + +HEX = '0123456789abcdef' +def rgb2hex(r,g,b): + return format((r<<16)|(g<<8)|b, '06x') + + +gexf = xml.dom.minidom.parse(sys.argv[1]) + +#Parse Attributes +nodesAttributes = []#The list of attributes of the nodes of the graph that we build in json +nodesAttributesDict={} +edgesAttributes = []#The list of attributes of the edges of the graph that we build in json +edgesAttributesDict={} + +#In the gexf (that is an xml), the list of xml nodes 'attributes' (note the plural 's') +attributesNodes = gexf.getElementsByTagName("attributes") +for attributesNode in attributesNodes: + if (attributesNode.getAttribute("class") == "node"): + attributeNodes = attributesNode.getElementsByTagName("attribute")#The list of xml nodes 'attribute' (no 's') + for attributeNodes in attributeNodes: + id = attributeNodes.getAttribute('id') + title = attributeNodes.getAttribute('title') + type = attributeNodes.getAttribute('type') + attribute = {"id":id, "title":title, "type":type} + nodesAttributes.append(attribute) + nodesAttributesDict[id]=title + elif (attributesNode.getAttribute("class")=="edge"): + attributeNodes = attributesNode.getElementsByTagName('attribute')#The list of xml nodes 'attribute' (no 's') + for attributeNode in attributeNodes: + #Each xml node 'attribute' + id = attributeNode.getAttribute('id') + title = attributeNode.getAttribute('title') + type = attributeNode.getAttribute('type') + + attribute = {"id":id, "title":title, "type":type} + edgesAttributes.append(attribute) + edgesAttributesDict[id]=title + +jsonNodes = []#The nodes of the graph +nodesNodes = gexf.getElementsByTagName("nodes")#The list of xml nodes 'nodes' (plural) + +for nodes in nodesNodes: + listNodes = nodes.getElementsByTagName("node")#The list of xml nodes 'node' (no 's') + for nodeEl in listNodes: + #Each xml node 'node' (no 's') + id = nodeEl.getAttribute('id') + title = nodeEl.getAttribute('title') + label = nodeEl.getAttribute('label') if nodeEl.hasAttribute("label") else id + + #viz + size = 1 + x = 100 - 200*random.random() + y = 100 - 200*random.random() + color="" + + #SAH: Original JS code tested for size.length in ternary; is len(...)!=0 appropriate replacement? + sizeNodes = nodeEl.getElementsByTagName('size') + sizeNodes = sizeNodes if len(sizeNodes)!=0 else nodeEl.getElementsByTagNameNS('*','size') + if(len(sizeNodes)>0): + sizeNode = sizeNodes[0]; + size = float(sizeNode.getAttribute('value')) + + #SAH save as sizeNodes + positionNodes = nodeEl.getElementsByTagName('position') + positionNodes = positionNodes if len(positionNodes)!=0 else nodeEl.getElementsByTagNameNS('*','position') + if(len(positionNodes)>0): + positionNode = positionNodes[0] + x = float(positionNode.getAttribute('x')) + y = float(positionNode.getAttribute('y')) + + + #SAH: really couldn't this be a function by now; same as above + colorNodes = nodeEl.getElementsByTagName('color') + colorNodes = colorNodes if len(colorNodes)!=0 else nodeEl.getElementsByTagNameNS('*','color') + if(len(colorNodes)>0): + colorNode = colorNodes[0] + color = '#'+rgb2hex(int(colorNode.getAttribute('r')), + int(colorNode.getAttribute('g')), + int(colorNode.getAttribute('b'))) + + #Create Node + node = {"id":id,"label":label, "size":size, "x":x, "y":y, "attributes":{}, "color":color}; #The graph node + + #Attribute values + attvalueNodes = nodeEl.getElementsByTagName("attvalue") + for attvalueNode in attvalueNodes: + attr = attvalueNode.getAttribute('for'); + val = attvalueNode.getAttribute('value'); + node["attributes"][nodesAttributesDict[attr]]=val + + jsonNodes.append(node) + +jsonEdges = [] +edgeId = 0 +edgesNodes = gexf.getElementsByTagName('edges') +for edgesNode in edgesNodes: + edgeNodes = edgesNode.getElementsByTagName('edge') + for edgeNode in edgeNodes: + source = edgeNode.getAttribute("source") + target = edgeNode.getAttribute("target") + label = edgeNode.getAttribute("label") + id = edgeNode.getAttribute("id") if edgeNode.hasAttribute("id") else edgeId + edgeId=edgeId+1 + + edge = { + "id": id, + "source": source, + "target": target, + "label": label, + "attributes": {} + } + + #Anything besies source,target,label that is inside the actual edge tag + attrs = edgeNode.attributes #NamedNodeMap in python + for i in range(0,attrs.length): + item=attrs.item(i)#xml.dom.minidom.Attr + n=item.name + if(n == 'source' or n =='target' or n=='label'): + continue; + edge["attributes"][n]=item.value + + #Redundant from block above + #if(edgeNode.hasAttribute("weight")): + # edge["weight"] = edgeNode.getAttribute('weight') + + attvalueNodes = edgeNode.getElementsByTagName('attvalue') + for attvalueNode in attvalueNodes: + attr = attvalueNode.getAttribute('for') + val = attvalueNode.getAttribute('value') + edge["attributes"][edgesAttributesDict[attr]]=val + + jsonEdges.append(edge) + +fhOutput = open(sys.argv[2],"w") +j={"nodes":jsonNodes,"edges":jsonEdges} +if len(sys.argv)>=4 and "pretty"==(sys.argv[3]).lower(): + json.dump(j,fhOutput,indent=4) +else: + json.dump(j,fhOutput) diff --git a/html/observatory/web.config b/html/observatory/web.config new file mode 100644 index 0000000..7345e31 --- /dev/null +++ b/html/observatory/web.config @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/shiny/observatory/.cfignore b/shiny/observatory/.cfignore new file mode 100644 index 0000000..c5d9d94 --- /dev/null +++ b/shiny/observatory/.cfignore @@ -0,0 +1,3 @@ +.Rproj.user +.Rhistory +.Rdata \ No newline at end of file diff --git a/shiny/observatory/agencycomparison.R b/shiny/observatory/agencycomparison.R new file mode 100644 index 0000000..f626671 --- /dev/null +++ b/shiny/observatory/agencycomparison.R @@ -0,0 +1,126 @@ +if (!exists("agency")){ + agency <- read.csv("agency-1000plus.csv", stringsAsFactors = FALSE)[,-1] +} + +if (!exists("all_agencies")){ + all_agencies <- read_xlsx("hostnames.xlsx", sheet = 1, col_names = F, col_types = "text") + colnames(all_agencies) <- c("hostnames") +} + + +if (!exists("large_agencies")){ + large_agencies <- read_xlsx("hostnames.xlsx", sheet = 2, col_names = F, col_types = "text") + colnames(large_agencies) <- c("hostnames") +} + +if (!exists("med_agencies")){ + med_agencies <- read_xlsx("hostnames.xlsx", sheet = 3, col_names = F, col_types = "text") + colnames(med_agencies) <- c("hostnames") +} + +if (!exists("small_agencies")){ + small_agencies <- read_xlsx("hostnames.xlsx", sheet = 4, col_names = F, col_types = "text") + colnames(small_agencies) <- c("hostnames") +} + + +agencyComparison <- tabPanel( + "Agency Comparison", # Sidebar with a slider input for number of bins + # Sidebar layout with input and output definitions ---- + sidebarLayout( + # Sidebar panel for inputs ---- + sidebarPanel( + # Input: Selector for choosing dataset ---- + selectInput( + inputId = "agencies", + label = "Choose an agency:", + choices = c("dta.gov.au", "humanservices.gov.au", "casa.gov.au") + ), + + selectInput( + inputId = "groups", + label = "Compare with:", + choices = c("small", "medium", "large", "all"), + ), + width = 3) + , + # Main panel for displaying outputs ---- + main = mainPanel( + # Output: Formatted text for caption ---- + h3(textOutput("ac_caption", container = span)), + # Output: Verbatim text for data summary ---- + verbatimTextOutput("ac_summary"), + # Output: HTML table with requested number of observations ---- + fluidRow( + splitLayout(cellWidths = c("50%", "50%"), plotOutput("view1"), plotOutput("view2")) + ) + ) + ) +) + + +agencycomparison_server <- function (input, output) { + # Return the requested dataset ---- + # By declaring datasetInput as a reactive expression we ensure + # that: + # + # 1. It is only called when the inputs it depends on changes + # 2. The computation and result are shared by all the callers, + # i.e. it only executes a single time + group_filter <- reactive({ + switch(input$groups, + "small" = small_agencies$hostnames, + "medium" = med_agencies$hostnames, + "large"= large_agencies$hostnames, + "all" = all_agencies$hostnames)}) + + datasetInput <- reactive({ + agency1 <- filter(agency, hostname == input$agencies) %>% + group_by(sourceurl) %>% + arrange(desc(tot_source)) + }) + + DatasetCompare <- reactive({ + agency <- filter(agency, hostname %in% group_filter()) %>% + group_by(sourceurl) %>% + arrange(desc(tot_source)) + }) + + output$ac_caption <- renderText({ + paste("Comparing referral sources from",input$agencies, " with ", input$groups, "agencies") + }) + + + output$view1 <- renderPlot({ + datasetInput() %>% + top_n(5) %>% + ggplot(aes(x="", y=tot_source, fill=sourceurl)) + + geom_bar(width = 1, stat = "identity")+ + coord_polar("y", start = 0) + + ylab(NULL)+ + theme(axis.text = element_blank(), + axis.ticks = element_blank(), + panel.grid = element_blank()) + + ggtitle("Single Agency referal sources") + + theme(legend.position = "none") + }) + + output$view2 <- renderPlot({ + DatasetCompare() %>% + group_by(sourceurl) %>% + top_n(5) %>% + ggplot(aes(x="", y=tot_source, fill = sourceurl)) + + geom_bar(width = 1, stat = "identity")+ + coord_polar("y", start = 0)+ + ylab(NULL)+ + theme(axis.text = element_blank(), + axis.ticks = element_blank(), + panel.grid = element_blank()) + + ggtitle("Cohort Agencies referal sources") + + theme(legend.position = "none") + }) + + +} + +shinyApp(ui = agencyComparison, server = agencycomparison_server) diff --git a/shiny/observatory/app.R b/shiny/observatory/app.R index 30791f7..2bb8bed 100644 --- a/shiny/observatory/app.R +++ b/shiny/observatory/app.R @@ -1,10 +1,19 @@ library(shiny) +library(dplyr) +library(magrittr) +library(ggplot2) +library(lubridate) +library(stringr) +library(readxl) +library(igraph) +library(networkD3) +library(lazyeval) library(r2d3) # Define UI ---- # User interface ---- -source("shinytester.R"); -source("painpoints.R"); +source("agencycomparison.R"); +source("siteuserjourneys.R"); source("userjourneys.R"); ui <- function() { suppressDependencies("bootstrap"); @@ -15,15 +24,20 @@ ui <- function() { subline = "To quantify interactions with every government service", # https://support.dominodatalab.com/hc/en-us/articles/360015932932-Increasing-the-timeout-for-Shiny-Server keepalive= textOutput("keepAlive"), - main = navbarPage("", userJourneys, shinyTester, painPoints) + main = navbarPage("", siteUserJourneys, agencyComparison, userJourneys) ) } # Define server logic to summarize and view selected dataset ---- server <- function(input, output) { - shinytester_server(input, output); - painpoints_server(input, output); + agencycomparison_server(input, output); userjourneys_server(input, output); + siteuserjourneys_server(input, output); + + output$keepAlive <- renderText({ + req(input$count) + paste("keep alive ", input$count) + }) } shinyApp(ui = ui, server = server) diff --git a/shiny/observatory/apt.yml b/shiny/observatory/apt.yml index 1085f15..f003659 100644 --- a/shiny/observatory/apt.yml +++ b/shiny/observatory/apt.yml @@ -6,4 +6,11 @@ packages: - r-base - r-base-dev - r-cran-littler - - r-cran-dplyr \ No newline at end of file + - r-cran-dplyr + - r-cran-magrittr + - r-cran-ggplot2 + - r-cran-lubridate + - r-cran-stringr + - r-cran-readxl + - r-cran-igraph + - r-cran-lazyeval diff --git a/shiny/observatory/hostnames.xlsx b/shiny/observatory/hostnames.xlsx new file mode 100644 index 0000000..d74d051 Binary files /dev/null and b/shiny/observatory/hostnames.xlsx differ diff --git a/shiny/observatory/manifest.yml b/shiny/observatory/manifest.yml index f056dd8..571a306 100644 --- a/shiny/observatory/manifest.yml +++ b/shiny/observatory/manifest.yml @@ -1,6 +1,21 @@ +--- +defaults: &defaults + buildpacks: + - apt_buildpack + - r_buildpack + memory: 2G + health-check-type: http + health-check-http-endpoint: /shared/shiny.css + sidecars: + - name: nginx + process_types: [ 'web' ] + command: "/home/vcap/deps/0/apt/usr/sbin/nginx -p . -c nginx.conf" applications: - - name: observatory - buildpacks: - - apt_buildpack - - r_buildpack - memory: 2G \ No newline at end of file + - name: observatory-green + routes: + - route: observatory-green.apps.y.cld.gov.au + <<: *defaults + - name: observatory-blue + routes: + - route: observatory-blue.apps.y.cld.gov.au + <<: *defaults \ No newline at end of file diff --git a/shiny/observatory/nginx.conf b/shiny/observatory/nginx.conf index 3a1da7c..08994f3 100644 --- a/shiny/observatory/nginx.conf +++ b/shiny/observatory/nginx.conf @@ -20,7 +20,11 @@ scgi_temp_path /tmp/uwsgi_temp 1 2; auth_basic "Administrator’s Area"; auth_basic_user_file htpasswd; - + location = /shared/shiny.css { + auth_basic off; + allow all; # Allow all to see content + proxy_pass http://localhost:3838/shared/shiny.css; + } access_log /dev/stdout cloudfoundry; default_type application/octet-stream; types { diff --git a/shiny/observatory/observatory.Rproj b/shiny/observatory/observatory.Rproj index 5c66677..228f973 100644 --- a/shiny/observatory/observatory.Rproj +++ b/shiny/observatory/observatory.Rproj @@ -11,8 +11,8 @@ Encoding: UTF-8 RnwWeave: Sweave LaTeX: pdfLaTeX - AutoAppendNewline: Yes StripTrailingWhitespace: Yes QuitChildProcessesOnExit: Yes + diff --git a/shiny/observatory/painpoints.R b/shiny/observatory/painpoints.R deleted file mode 100644 index 6a36b0b..0000000 --- a/shiny/observatory/painpoints.R +++ /dev/null @@ -1,16 +0,0 @@ -painPoints <- tabPanel( - "Pain Points", # Sidebar with a slider input for number of bins - # Sidebar layout with input and output definitions ---- - sidebarLayout( - # Sidebar panel for inputs ---- - sidebarPanel( - ) - , - # Main panel for displaying outputs ---- - main = mainPanel( - ) - ) -) - -painpoints_server <- function (input, output) { -} \ No newline at end of file diff --git a/shiny/observatory/r.yml b/shiny/observatory/r.yml index 4d94800..98d31ce 100644 --- a/shiny/observatory/r.yml +++ b/shiny/observatory/r.yml @@ -2,5 +2,6 @@ packages: - cran_mirror: https://cran.csiro.au packages: + - name: networkD3 - name: shiny - name: r2d3 \ No newline at end of file diff --git a/shiny/observatory/run.sh b/shiny/observatory/run.sh index 6f53bb4..eda4d99 100644 --- a/shiny/observatory/run.sh +++ b/shiny/observatory/run.sh @@ -1,13 +1,13 @@ #!/usr/bin/env bash -if [ ! -f setup_complete ]; then +if [[ ! -f setup_complete ]]; then for dir in /home/vcap/deps/0/apt/usr/lib/R/site-library/*; do if [[ ! "$dir" =~ (htmlwidgets|shiny|httpuv) ]]; then - echo installing $dir; - R CMD INSTALL $dir; + echo installing ${dir}; + R CMD INSTALL ${dir} ; fi done + wait /home/vcap/deps/0/apt/usr/sbin/nginx -V touch setup_complete fi -/home/vcap/deps/0/apt/usr/sbin/nginx -p . -c nginx.conf & R -e "options(shiny.port = 3838); shiny::runApp(getwd())" diff --git a/shiny/observatory/shinytester.R b/shiny/observatory/shinytester.R deleted file mode 100644 index 19a3116..0000000 --- a/shiny/observatory/shinytester.R +++ /dev/null @@ -1,95 +0,0 @@ -shinyTester <- tabPanel( - "Shiny Tester", # Sidebar with a slider input for number of bins - # Sidebar layout with input and output definitions ---- - sidebarLayout( - # Sidebar panel for inputs ---- - sidebarPanel( - # Input: Text for providing a caption ---- - # Note: Changes made to the caption in the textInput control - # are updated in the output area immediately as you type - textInput( - inputId = "caption", - label = "Caption:", - - value = "Data Summary" - ), - # Input: Selector for choosing dataset ---- - selectInput( - inputId = "dataset", - label = "Choose a dataset:", - choices = c("rock", "pressure", "cars") - ), - # Input: Numeric entry for number of obs to view ---- - numericInput( - inputId = "obs", - label = "Number of observations to view:", - value = 10 - ) - ) - , - # Main panel for displaying outputs ---- - main = mainPanel( - # Output: Formatted text for caption ---- - h3(textOutput("caption", container = span)), - # Output: Verbatim text for data summary ---- - verbatimTextOutput("summary"), - # Output: HTML table with requested number of observations ---- - tableOutput("view") - - ) - ) -) - -shinytester_server <- function (input, output) { - # Return the requested dataset ---- - # By declaring datasetInput as a reactive expression we ensure - # that: - # - # 1. It is only called when the inputs it depends on changes - # 2. The computation and result are shared by all the callers, - # i.e. it only executes a single time - datasetInput <- reactive({ - switch( - input$dataset, - "rock" = rock, - "pressure" = pressure, - "cars" = cars - ) - }) - - # Create caption ---- - # The output$caption is computed based on a reactive expression - # that returns input$caption. When the user changes the - # "caption" field: - # - # 1. This function is automatically called to recompute the output - # 2. New caption is pushed back to the browser for re-display - # - # Note that because the data-oriented reactive expressions - # below don't depend on input$caption, those expressions are - # NOT called when input$caption changes - output$caption <- renderText({ - input$caption - }) - - # Generate a summary of the dataset ---- - # The output$summary depends on the datasetInput reactive - # expression, so will be re-executed whenever datasetInput is - # invalidated, i.e. whenever the input$dataset changes - output$summary <- renderPrint({ - dataset <- datasetInput() - summary(dataset) - }) - - # Show the first "n" observations ---- - # The output$view depends on both the databaseInput reactive - # expression and input$obs, so it will be re-executed whenever - # input$dataset or input$obs is changed - output$view <- renderTable({ - head(datasetInput(), n = input$obs) - }) - output$keepAlive <- renderText({ - req(input$count) - paste("keep alive ", input$count) - }) -} \ No newline at end of file diff --git a/shiny/observatory/siteuserjourneys.R b/shiny/observatory/siteuserjourneys.R new file mode 100644 index 0000000..9d0108b --- /dev/null +++ b/shiny/observatory/siteuserjourneys.R @@ -0,0 +1,24 @@ +siteUserJourneys <- tabPanel( +"User Journeys", +d3Output("d3", width = "100%", height = 800) +) + +siteuserjourneys_server <- function (input, output) { + output$d3 <- renderD3({ + r2d3( + list(data.frame(title = c("DTA","About Us","Join Our Team","Recruiterbox"), + href=c("https://google.com","https://google.com","https://google.com","")), + data.frame(title = c("DTA","Blogs", "Help and Advice", "Guides and Tools", "Homepage - Digital Guides", "Topics", "Roles", "What each role does","Content guide","New to content design?"), + href=c("https://google.com","https://google.com","https://google.com"," "," "," "," "," "," "," ")), + data.frame(title = c("Domain Names","Guidelines", "Name Server Change"), + href=c("https://google.com","https://google.com","https://google.com")), + data.frame(title = c("Design System","Components", "Templates"), + href=c("https://google.com","https://google.com","https://google.com")), + data.frame(title = c("Design System","Get Started", "Download", "Community"), + href=c("https://google.com","https://google.com","https://google.com", "")) + ), + script = "siteuserjourneys.js" + ) + }) +} +shinyApp(ui = siteUserJourneys, server = siteuserjourneys_server) diff --git a/shiny/observatory/siteuserjourneys.js b/shiny/observatory/siteuserjourneys.js new file mode 100644 index 0000000..6b7eeee --- /dev/null +++ b/shiny/observatory/siteuserjourneys.js @@ -0,0 +1,83 @@ +// !preview r2d3 data=list(data.frame(title = c("DTA","About Us","Join Our Team","Recruiterbox","5","6","7","8"),href=c("https://google.com","https://google.com","https://google.com","","","","","")), data.frame(title = c("DTA","Blogs", "Help and Advice"),href=c("https://google.com","https://google.com","https://google.com")), data.frame(title = c("Domain Names","Guidelines", "Name Server Change"),href=c("https://google.com","https://google.com","https://google.com")), data.frame(title = c("Design System","Components", "Templates"),href=c("https://google.com","https://google.com","https://google.com")), data.frame(title = c("Design System","Get Started", "Download", "Community"),href=c("https://google.com","https://google.com","https://google.com", ""))),height=800,width="100%" + + +r2d3.svg.selectAll("svg > *").remove(); +var g = r2d3.svg + .selectAll() + .data(data) + .enter() + .append("g") + .attr("transform", function (d, i) { + return "translate(" + 15 + "," + (Math.abs(i) * 130) + ")"; + }); + +function dx(d, i) { + return i * 100 + 50; +} + +function dy(d, i) { + return 50; +} + +var lineFunction = d3 + .line() + .x(function (d, i) { + return dx(d, i); + }) + .y(function (d, i) { + return dy(d, i); + }) + .curve(d3.curveLinear); +var line = g + .append("path") + .attr("d", function (d) { + return lineFunction(d.title); + }) + .attr("stroke", "grey") + .attr("stroke-width", 10) + .attr("fill", "white"); + +var circles = g.selectAll().data(function (d) { + return HTMLWidgets.dataframeToD3(d); +}); +circles + .enter() + .append("circle") + .attr("cy", function (d, i) { + return dy(d, i); + }) + .attr("cx", function (d, i) { + return dx(d, i); + }) + .attr("r", 20) + .attr("fill", "white") + .attr("stroke", "grey") + .attr("stroke-width", "10px"); + +var texts = g + .selectAll() + .data(function (d) { + return HTMLWidgets.dataframeToD3(d); + }) + .enter() + .append("foreignObject") + .attr("x", function (d, i) { + return dx(d, i)-10; + }) + .attr("y", function (d, i) { + return dy(d, i); + }) + .attr("width", function (d, i) { + return 115; + }) + .attr("height", function (d, i) { + return 110; + }) + .append("xhtml:p") + .style("text-align", "left") + .style("padding-left", "30px") + .style("transform-origin", "0 0") + .style("transform","rotate(25deg)") + .html(function (d) { + return d.title; + }); diff --git a/shiny/observatory/template.html b/shiny/observatory/template.html index 204a454..85c0a44 100644 --- a/shiny/observatory/template.html +++ b/shiny/observatory/template.html @@ -4,89 +4,89 @@ {{ title }} {{ - headContent() + headContent() }} - - + - +{{ keepalive }} + +
    + +
    +
    + {{ main }} +
    -
    -
    - -
    -
    - +
    +
    + +
    +
    +
    -
    +
    +
    diff --git a/shiny/observatory/uj_all.rdata b/shiny/observatory/uj_all.rdata new file mode 100644 index 0000000..46d99e8 --- /dev/null +++ b/shiny/observatory/uj_all.rdata @@ -0,0 +1,1796 @@ +*Vertices 1281 +*Arcs +1 97 3976 +1 112 271954 +1 116 4763 +1 118 3308 +1 119 128456 +1 120 4374 +1 121 17821 +1 122 5962 +1 123 8766 +1 127 66235 +1 128 2187 +1 129 3754 +1 130 6002 +1 132 15648 +1 133 4629 +1 134 30665 +1 136 32819 +1 137 896097 +1 138 43594 +1 139 14620 +1 140 248388 +1 142 307084 +1 143 2957 +1 144 2923 +1 149 10431 +1 152 2385 +1 153 9518 +1 154 14338 +1 155 2719 +1 157 3452 +1 158 24707 +1 159 2462 +1 160 4111 +1 163 30300 +1 164 12896 +1 165 22909 +1 167 2359 +1 170 2028 +1 172 2858 +1 174 2591 +1 176 2865 +1 177 3824 +1 188 6536 +1 193 35988 +1 197 3890 +1 199 7900 +1 200 4225 +1 201 2362 +1 202 12622 +1 203 8679 +1 204 2518 +1 205 2329 +1 206 5348 +1 209 2036 +1 214 7517 +1 215 4218 +1 220 2530 +1 222 3134 +1 229 3015 +1 231 3897 +1 232 3000 +1 233 2197 +1 236 2834 +1 251 4779 +1 254 2024 +1 255 3625 +1 260 2061 +1 267 9243 +1 272 3686 +1 281 5143 +1 284 5404 +1 285 2448 +1 298 3853 +1 303 2738 +1 304 2527 +1 305 2198 +1 308 29142 +1 355 3801 +1 359 149451 +1 360 143923 +1 361 33237 +1 364 2712 +1 367 3286 +1 368 70555 +1 370 22386 +1 371 5108 +1 372 7196 +1 373 13842 +1 374 2647 +1 375 14162 +1 376 8743 +1 378 9773 +1 379 2015 +1 380 45371 +1 382 8627 +1 383 11889 +1 389 2873 +1 393 20418 +1 394 3700 +1 396 19013 +1 399 14596 +1 400 2949 +1 403 2070 +1 405 4153 +1 409 3604 +1 414 4138 +1 415 8347 +1 417 14339 +1 421 3728 +1 423 2410 +1 425 3000 +1 428 24087 +1 432 3807 +1 433 2700 +1 435 2280 +1 436 8002 +1 438 3017 +1 443 5937 +1 446 3290 +1 447 6242 +1 453 3644 +1 455 6557 +1 456 2492 +1 457 3734 +1 460 2574 +1 464 5411 +1 465 4085 +1 466 17617 +1 467 25555 +1 470 4175 +1 472 4332 +1 480 2261 +1 481 3141 +1 483 31590 +1 484 11573 +1 487 3863 +1 488 3892 +1 491 6525 +1 492 2753 +1 495 9214 +1 497 2906 +1 499 14588 +1 503 7109 +1 506 2928 +1 511 3339 +1 512 2681 +1 516 2323 +1 521 2955 +1 522 4945 +1 526 3552 +1 527 4606 +1 528 3402 +1 529 2193 +1 538 4465 +1 539 3532 +1 542 2639 +1 543 2284 +1 544 3596 +1 546 6830 +1 551 27119 +1 553 7061 +1 555 4487 +1 556 4450 +1 557 2296 +1 560 6567 +1 562 3442 +1 563 5296 +1 565 2119 +1 566 3258 +1 571 4184 +1 575 5340 +1 581 2011 +1 583 3681 +1 585 4296 +1 588 2986 +1 591 2731 +1 593 2851 +1 603 4119 +1 610 2264 +1 613 3421 +1 614 3526 +1 616 2161 +1 619 4595 +1 623 2757 +1 627 2615 +1 628 5893 +1 633 2716 +1 635 2058 +1 637 2720 +1 644 3477 +1 646 4818 +1 647 3289 +1 649 3154 +1 662 2495 +1 663 4862 +1 666 4851 +1 674 2936 +1 677 2789 +1 683 4360 +1 685 16698 +1 687 2178 +1 701 2214 +1 712 2313 +1 714 2123 +1 715 4179 +1 716 4195 +1 717 2122 +1 718 4095 +1 725 4141 +1 726 2341 +1 730 3593 +1 735 2028 +1 737 2105 +1 738 2685 +1 741 3788 +1 744 3988 +1 747 2926 +1 758 5241 +1 760 2040 +1 766 3456 +1 773 2726 +1 778 2241 +1 779 4288 +1 785 8104 +1 787 3030 +1 795 3563 +1 810 7276 +1 815 3463 +1 826 3007 +1 829 3355 +1 832 2104 +1 833 4428 +1 837 3725 +1 845 2181 +1 847 4929 +1 864 2247 +1 871 3171 +1 874 4239 +1 879 10755 +1 880 2780 +1 881 5106 +1 883 9100 +1 884 40102 +1 885 3483 +1 886 2842 +1 890 3940 +1 891 14481 +1 893 2582 +1 894 2053 +1 895 4377 +1 896 5430 +1 898 3556 +1 905 11114 +1 911 3209 +1 913 12597 +1 917 40568 +1 918 3267 +1 919 3843 +1 923 2200 +1 925 3626 +1 927 3496 +1 938 2623 +1 940 2629 +1 945 2377 +1 957 3753 +1 963 3576 +1 969 25401 +1 970 3783 +1 972 14902 +1 998 4189 +1 1005 7963 +1 1011 6127 +1 1025 2061 +1 1029 2722 +1 1030 10044 +1 1031 8432 +1 1032 2591 +1 1033 2775 +1 1038 2287 +1 1043 5552 +1 1046 7022 +1 1048 2062 +1 1050 6456 +1 1054 6610 +1 1057 2860 +1 1066 7244 +1 1073 2898 +1 1079 2660 +1 1099 2211 +1 1100 2508 +1 1115 3082 +1 1120 5222 +1 1132 3231 +1 1139 2628 +1 1152 2541 +1 1153 3467 +1 1154 2941 +1 1166 7938 +1 1247 3565 +1 1254 2550 +1 1263 7841 +1 1280 2102 +2 112 106317 +2 119 6645 +2 359 9400 +2 360 18671 +2 368 12380 +2 380 2054 +2 396 2220 +3 112 3703 +4 112 2116 +5 112 108810 +5 116 2844 +5 119 24304 +5 131 2225 +5 359 17406 +5 360 4417 +5 372 3856 +5 375 3927 +5 378 2573 +5 381 4840 +5 382 2490 +5 383 4663 +5 396 4092 +5 399 5406 +5 417 6769 +5 428 2805 +5 430 3754 +5 443 2340 +5 446 2569 +5 447 2582 +5 457 7673 +5 464 2389 +5 466 5546 +5 484 2667 +5 492 2219 +5 499 2942 +5 503 2103 +5 504 2245 +5 526 2076 +5 538 2618 +5 546 2791 +5 566 2848 +5 649 2037 +5 662 2066 +5 663 2556 +5 946 2668 +5 1158 4476 +5 1162 2094 +5 1207 2381 +5 1214 2113 +5 1226 2415 +6 36 24850 +6 43 6167 +6 54 2530 +6 55 14470 +6 65 4106 +6 77 2460 +6 78 4324 +6 82 7249 +6 86 4031 +6 88 2455 +6 89 6956 +6 90 2663 +6 91 2431 +6 92 4342 +6 93 4381 +6 94 10090 +6 95 3892 +6 96 2551 +6 99 4483 +6 100 4414 +6 101 6031 +6 102 3680 +6 103 2359 +6 104 3026 +6 105 6271 +6 106 3526 +6 107 5954 +6 108 2145 +6 109 2366 +6 110 2048 +6 111 2122 +6 112 422374 +6 114 9296 +6 115 4477 +6 116 36166 +6 117 12613 +6 118 8562 +6 119 536991 +6 120 38891 +6 121 32883 +6 122 17583 +6 123 24203 +6 124 4838 +6 126 6767 +6 127 62805 +6 128 4766 +6 129 3285 +6 130 3802 +6 131 8087 +6 132 23202 +6 133 6119 +6 134 74225 +6 135 2391 +6 136 12014 +6 138 71613 +6 139 38955 +6 140 30476 +6 141 8166 +6 142 100056 +6 143 5837 +6 145 10092 +6 146 2452 +6 147 3319 +6 148 17187 +6 149 92331 +6 150 30387 +6 151 2362 +6 154 11533 +6 155 3202 +6 156 2324 +6 158 2051 +6 159 12677 +6 160 13342 +6 161 3007 +6 162 6473 +6 163 22326 +6 165 62423 +6 166 4486 +6 168 7106 +6 169 2706 +6 170 2759 +6 171 2674 +6 172 3466 +6 173 4882 +6 174 9705 +6 175 8310 +6 176 55013 +6 177 54343 +6 178 19254 +6 179 4715 +6 180 4781 +6 181 2951 +6 182 8302 +6 183 10201 +6 184 4970 +6 185 8501 +6 186 5295 +6 187 8278 +6 189 4084 +6 190 4908 +6 191 19069 +6 192 3485 +6 193 33030 +6 194 4694 +6 195 6229 +6 196 4731 +6 197 11373 +6 198 15203 +6 206 2080 +6 207 2467 +6 208 3875 +6 209 13219 +6 210 12332 +6 211 4026 +6 212 20366 +6 213 16361 +6 215 8995 +6 216 4930 +6 217 4495 +6 218 3202 +6 219 3419 +6 220 20284 +6 221 3427 +6 222 2565 +6 223 3399 +6 224 2877 +6 225 3283 +6 226 2524 +6 227 4628 +6 228 3608 +6 229 2243 +6 230 5468 +6 233 5391 +6 234 6701 +6 235 11172 +6 236 20854 +6 237 3087 +6 238 3718 +6 239 3813 +6 240 4595 +6 241 4550 +6 242 2921 +6 243 11421 +6 244 3053 +6 245 14070 +6 246 2673 +6 247 3045 +6 248 3705 +6 249 2114 +6 250 3768 +6 252 2994 +6 253 3213 +6 255 7900 +6 256 3086 +6 257 3511 +6 258 3526 +6 259 2049 +6 260 2782 +6 261 3064 +6 262 2138 +6 263 4701 +6 264 4054 +6 265 2197 +6 266 5466 +6 268 2342 +6 269 4599 +6 270 2061 +6 271 2995 +6 273 3115 +6 274 2322 +6 275 3580 +6 276 3556 +6 277 2943 +6 278 2931 +6 279 3470 +6 280 8734 +6 282 3139 +6 283 8253 +6 286 2662 +6 287 4569 +6 288 4591 +6 290 2767 +6 291 2080 +6 292 2324 +6 293 2265 +6 294 6053 +6 295 2417 +6 296 2048 +6 297 3927 +6 299 3411 +6 300 4516 +6 301 3014 +6 302 6982 +6 306 2041 +6 307 3211 +6 308 7404 +6 309 3121 +6 310 2382 +6 311 2204 +6 312 4931 +6 313 2031 +6 314 2408 +6 315 3926 +6 316 2419 +6 317 2357 +6 318 2636 +6 319 4016 +6 320 2408 +6 321 2290 +6 322 2587 +6 323 5105 +6 324 2437 +6 325 4514 +6 326 4488 +6 327 3379 +6 328 2106 +6 329 3370 +6 330 5402 +6 331 4164 +6 332 2600 +6 333 2470 +6 334 4425 +6 335 3454 +6 336 3961 +6 337 2982 +6 338 2441 +6 339 3246 +6 340 3804 +6 341 2739 +6 342 2860 +6 343 3631 +6 344 2707 +6 345 14517 +6 346 2973 +6 347 2176 +6 348 3867 +6 349 2365 +6 350 2128 +6 351 4677 +6 352 2600 +6 353 3496 +6 354 2239 +6 356 2290 +6 357 2343 +6 358 8944 +6 359 263730 +6 360 835332 +6 361 36793 +6 362 18167 +6 363 3746 +6 364 29998 +6 365 4571 +6 366 2189 +6 367 40041 +6 368 206384 +6 369 6852 +6 370 60005 +6 371 33523 +6 372 73050 +6 373 22466 +6 374 26199 +6 375 89562 +6 376 17251 +6 377 4622 +6 378 54203 +6 379 15266 +6 380 105928 +6 381 4651 +6 382 34054 +6 383 116351 +6 384 3896 +6 385 15906 +6 386 6320 +6 387 11925 +6 388 2103 +6 389 15155 +6 390 2800 +6 391 8865 +6 392 2178 +6 393 29589 +6 394 23534 +6 395 17471 +6 396 26231 +6 397 4956 +6 398 7688 +6 399 84757 +6 400 35109 +6 401 15761 +6 402 3239 +6 403 41955 +6 404 2182 +6 405 28518 +6 406 2501 +6 407 3001 +6 408 3558 +6 409 43226 +6 410 16294 +6 411 4343 +6 412 5080 +6 413 2101 +6 414 5073 +6 415 10607 +6 416 6453 +6 417 31763 +6 419 3871 +6 420 5919 +6 421 38073 +6 422 22705 +6 423 10889 +6 424 2898 +6 425 22148 +6 426 12766 +6 427 4474 +6 428 145675 +6 429 3724 +6 431 13329 +6 432 13704 +6 433 29617 +6 434 7397 +6 435 12137 +6 436 25710 +6 437 3290 +6 438 20759 +6 439 6196 +6 440 2390 +6 441 2565 +6 442 7668 +6 443 32259 +6 444 8142 +6 445 2663 +6 446 38339 +6 447 91136 +6 449 2528 +6 450 2059 +6 451 3262 +6 452 2615 +6 453 23703 +6 454 13821 +6 455 28020 +6 456 10318 +6 457 5163 +6 458 3976 +6 459 2044 +6 460 10442 +6 461 8296 +6 463 6001 +6 464 153067 +6 465 22407 +6 466 70779 +6 467 52239 +6 468 2128 +6 469 6235 +6 470 33954 +6 471 8880 +6 472 19454 +6 473 10538 +6 474 3901 +6 475 5029 +6 476 11479 +6 477 4491 +6 478 3308 +6 479 3422 +6 480 33833 +6 481 2875 +6 482 2580 +6 483 155598 +6 484 74198 +6 485 2307 +6 486 3075 +6 487 25842 +6 488 19223 +6 489 9797 +6 490 5658 +6 491 28828 +6 492 31174 +6 493 8122 +6 494 8352 +6 495 34798 +6 496 22333 +6 497 43588 +6 498 7922 +6 499 50876 +6 500 6277 +6 501 14369 +6 502 14266 +6 503 45131 +6 504 10653 +6 505 19196 +6 506 47129 +6 507 12625 +6 508 4650 +6 509 5069 +6 510 3517 +6 511 27844 +6 512 42266 +6 513 2387 +6 514 21659 +6 515 12613 +6 516 24728 +6 517 2765 +6 518 4621 +6 519 10269 +6 520 4684 +6 521 21107 +6 522 21226 +6 523 14020 +6 524 4558 +6 525 2755 +6 526 11266 +6 527 6934 +6 528 7078 +6 529 4570 +6 530 6423 +6 532 2434 +6 533 4035 +6 534 2998 +6 535 2682 +6 536 4917 +6 537 4347 +6 538 24149 +6 539 3504 +6 540 2575 +6 541 2677 +6 543 29386 +6 544 35089 +6 545 2118 +6 546 61539 +6 547 2875 +6 548 24390 +6 549 5573 +6 550 4321 +6 551 42306 +6 552 8639 +6 553 75130 +6 554 6699 +6 555 18677 +6 556 13765 +6 557 23290 +6 558 20620 +6 559 3129 +6 560 12578 +6 561 10948 +6 562 31076 +6 563 5606 +6 564 7144 +6 565 9642 +6 566 65392 +6 567 2019 +6 568 12864 +6 569 8400 +6 570 6036 +6 571 49713 +6 572 2741 +6 573 2921 +6 574 3766 +6 575 19980 +6 576 27106 +6 577 5094 +6 578 5718 +6 579 11607 +6 580 11874 +6 581 17425 +6 582 9772 +6 583 22096 +6 584 2992 +6 585 50200 +6 586 9415 +6 587 2025 +6 588 40449 +6 589 12794 +6 590 8399 +6 591 18261 +6 592 2231 +6 593 14887 +6 594 5798 +6 595 13465 +6 596 4980 +6 597 25396 +6 598 3468 +6 599 4044 +6 600 12054 +6 601 3145 +6 602 2976 +6 603 29685 +6 604 5192 +6 605 3419 +6 606 4677 +6 607 5909 +6 608 16602 +6 609 9498 +6 610 13330 +6 611 31906 +6 612 2085 +6 613 15550 +6 614 11603 +6 615 11795 +6 616 18792 +6 617 3377 +6 618 2186 +6 619 24397 +6 620 5034 +6 621 3829 +6 622 9050 +6 623 13809 +6 624 23611 +6 625 5895 +6 626 7963 +6 627 24280 +6 628 48714 +6 629 5562 +6 630 10283 +6 631 10750 +6 632 3507 +6 633 11821 +6 634 3151 +6 635 4854 +6 636 4539 +6 637 6429 +6 638 2579 +6 639 15144 +6 640 3803 +6 641 3438 +6 642 4063 +6 643 3732 +6 644 2922 +6 645 3486 +6 646 63594 +6 647 16910 +6 648 9152 +6 649 47201 +6 650 2429 +6 651 2369 +6 652 3323 +6 653 3286 +6 654 5290 +6 655 7491 +6 656 13571 +6 657 6955 +6 658 2348 +6 659 4269 +6 660 2137 +6 661 6210 +6 662 37109 +6 663 27339 +6 664 3810 +6 665 8698 +6 666 13913 +6 667 4403 +6 668 23428 +6 669 2666 +6 670 4985 +6 671 3513 +6 672 5819 +6 673 14596 +6 674 7101 +6 675 5147 +6 676 5185 +6 677 9229 +6 678 13001 +6 679 9828 +6 680 6639 +6 681 4034 +6 682 2159 +6 683 28548 +6 684 2876 +6 686 3955 +6 687 2803 +6 688 7465 +6 689 4401 +6 690 4324 +6 691 2148 +6 692 13979 +6 693 16419 +6 694 24752 +6 695 8754 +6 696 9163 +6 697 2570 +6 698 3992 +6 699 2913 +6 700 2532 +6 701 7880 +6 702 4690 +6 703 7858 +6 704 5490 +6 705 21774 +6 706 7620 +6 707 5126 +6 708 3148 +6 709 2256 +6 710 15014 +6 711 15969 +6 712 4604 +6 713 10616 +6 714 3733 +6 715 29157 +6 716 18866 +6 717 6576 +6 718 2033 +6 719 4367 +6 720 2195 +6 721 2521 +6 722 6153 +6 723 3908 +6 724 6942 +6 725 30216 +6 726 22412 +6 727 6939 +6 728 2020 +6 729 24005 +6 730 15029 +6 731 11274 +6 732 5457 +6 733 3185 +6 734 3737 +6 735 10490 +6 736 2044 +6 737 6417 +6 738 27860 +6 739 19232 +6 740 2805 +6 741 7087 +6 742 14571 +6 743 3015 +6 744 4853 +6 745 6078 +6 746 4278 +6 747 3247 +6 748 11514 +6 749 4945 +6 750 5615 +6 751 4250 +6 752 2749 +6 753 2821 +6 754 3989 +6 755 12032 +6 756 2125 +6 757 6893 +6 758 7197 +6 759 5593 +6 760 47197 +6 761 16298 +6 762 14252 +6 763 6497 +6 764 2959 +6 765 3101 +6 766 10643 +6 767 2446 +6 768 2873 +6 769 5974 +6 770 6242 +6 771 3504 +6 772 4315 +6 773 25099 +6 774 16934 +6 775 23654 +6 776 5346 +6 777 8116 +6 778 8396 +6 779 24299 +6 780 5888 +6 781 2974 +6 782 11028 +6 783 4062 +6 784 4980 +6 785 22598 +6 786 8967 +6 787 6447 +6 788 2986 +6 789 3559 +6 790 2314 +6 791 2763 +6 792 7333 +6 793 3873 +6 794 5058 +6 795 20906 +6 796 2653 +6 797 2893 +6 798 4036 +6 799 2661 +6 800 2315 +6 801 5411 +6 802 9849 +6 803 4736 +6 804 4028 +6 805 2394 +6 806 3776 +6 807 7926 +6 808 2856 +6 809 2310 +6 811 2034 +6 812 4612 +6 813 2370 +6 814 6143 +6 815 36632 +6 816 6771 +6 817 5334 +6 818 7030 +6 819 4892 +6 820 2008 +6 821 5387 +6 822 4037 +6 823 2758 +6 824 5333 +6 825 2904 +6 826 24955 +6 827 2271 +6 828 18146 +6 829 27119 +6 830 11813 +6 831 15660 +6 833 18136 +6 834 4642 +6 835 6568 +6 836 2281 +6 837 5873 +6 838 3459 +6 839 5814 +6 840 6194 +6 841 2153 +6 842 2485 +6 843 16528 +6 844 2337 +6 845 11428 +6 846 2109 +6 848 7646 +6 849 6089 +6 850 3813 +6 851 5744 +6 852 2059 +6 853 4482 +6 854 24378 +6 855 2087 +6 856 7766 +6 857 3113 +6 858 4112 +6 859 3488 +6 860 12793 +6 861 2534 +6 862 11121 +6 863 3048 +6 864 11691 +6 865 2147 +6 866 3549 +6 867 9200 +6 868 2104 +6 869 2049 +6 870 4345 +6 871 5439 +6 872 2549 +6 873 3526 +6 874 13221 +6 875 2394 +6 877 3593 +6 878 3506 +6 879 14776 +6 880 86282 +6 881 20614 +6 882 26614 +6 883 14287 +6 884 101254 +6 885 38790 +6 886 12873 +6 887 30207 +6 888 4864 +6 889 4338 +6 890 2586 +6 891 10726 +6 892 2784 +6 893 8224 +6 894 8461 +6 897 3619 +6 898 9513 +6 899 7180 +6 900 2921 +6 901 3596 +6 902 6001 +6 903 2733 +6 904 4455 +6 905 2882 +6 906 2307 +6 907 2940 +6 908 3307 +6 909 12725 +6 910 13735 +6 911 27545 +6 912 14764 +6 913 13624 +6 914 16844 +6 915 4574 +6 916 2074 +6 917 16587 +6 918 2862 +6 919 8069 +6 920 2522 +6 921 2490 +6 923 4878 +6 924 7650 +6 925 48606 +6 926 2355 +6 928 3060 +6 929 4403 +6 930 2636 +6 931 6280 +6 932 2109 +6 933 3971 +6 934 2344 +6 935 2437 +6 939 2909 +6 940 2345 +6 944 2774 +6 945 2808 +6 947 4161 +6 948 2779 +6 949 2348 +6 950 2035 +6 951 5462 +6 952 2717 +6 953 2933 +6 954 8831 +6 955 2108 +6 956 9293 +6 957 2658 +6 958 4061 +6 959 3226 +6 961 6047 +6 962 11737 +6 963 6069 +6 964 4750 +6 965 4195 +6 966 3434 +6 967 4322 +6 968 15416 +6 969 2373 +6 970 7919 +6 973 2023 +6 974 3428 +6 975 3378 +6 976 2151 +6 977 10085 +6 978 3487 +6 979 8025 +6 980 3030 +6 981 7408 +6 982 3423 +6 983 2913 +6 984 2486 +6 985 12455 +6 986 12206 +6 989 3379 +6 990 4106 +6 991 2775 +6 992 10040 +6 993 4620 +6 994 12349 +6 995 2079 +6 996 3709 +6 997 3565 +6 998 14218 +6 999 2257 +6 1000 7496 +6 1001 2065 +6 1002 2880 +6 1003 3805 +6 1004 2602 +6 1005 15239 +6 1006 3254 +6 1007 3597 +6 1008 4310 +6 1009 3975 +6 1013 2425 +6 1014 9259 +6 1015 6663 +6 1016 5047 +6 1017 10983 +6 1018 2373 +6 1019 2041 +6 1020 2718 +6 1021 5153 +6 1022 6087 +6 1023 2154 +6 1024 6887 +6 1025 3535 +6 1026 3712 +6 1028 2495 +6 1029 3927 +6 1030 18836 +6 1031 18373 +6 1032 3306 +6 1033 4669 +6 1034 5236 +6 1035 3754 +6 1036 2498 +6 1037 3501 +6 1038 4998 +6 1039 3365 +6 1040 4230 +6 1041 2621 +6 1042 6721 +6 1043 4972 +6 1044 2243 +6 1045 5129 +6 1046 6676 +6 1047 5349 +6 1048 2080 +6 1049 4678 +6 1051 2347 +6 1052 3252 +6 1054 5005 +6 1055 2350 +6 1056 6727 +6 1057 7234 +6 1058 3505 +6 1059 3704 +6 1060 2411 +6 1061 5395 +6 1062 4797 +6 1063 6494 +6 1064 3276 +6 1065 3198 +6 1067 2429 +6 1068 3097 +6 1069 2631 +6 1070 8877 +6 1071 4941 +6 1072 2180 +6 1074 5286 +6 1075 2730 +6 1076 8708 +6 1077 5864 +6 1078 3888 +6 1079 5485 +6 1080 2682 +6 1082 3636 +6 1083 3121 +6 1084 2071 +6 1085 4092 +6 1086 2223 +6 1087 4545 +6 1088 7403 +6 1089 2423 +6 1090 3656 +6 1091 3584 +6 1093 3039 +6 1094 2027 +6 1095 2029 +6 1096 2222 +6 1097 3204 +6 1098 2477 +6 1101 5764 +6 1102 2961 +6 1103 5885 +6 1104 5590 +6 1105 2827 +6 1106 2543 +6 1107 2222 +6 1108 2906 +6 1109 2594 +6 1110 4691 +6 1112 2517 +6 1113 2958 +6 1114 2186 +6 1115 2157 +6 1116 2571 +6 1117 2282 +6 1118 3125 +6 1119 4114 +6 1120 3142 +6 1121 2075 +6 1122 3256 +6 1123 4594 +6 1124 2316 +6 1125 3406 +6 1126 5128 +6 1127 2998 +6 1128 2385 +6 1129 2464 +6 1130 2456 +6 1132 3589 +6 1133 2934 +6 1134 2156 +6 1135 2837 +6 1136 2525 +6 1137 4483 +6 1138 2214 +6 1140 5203 +6 1141 2582 +6 1142 2835 +6 1143 3072 +6 1144 2326 +6 1145 12771 +6 1146 2160 +6 1147 2912 +6 1148 6710 +6 1150 2441 +6 1151 6308 +6 1153 4495 +6 1155 2439 +6 1156 3557 +6 1157 3177 +6 1159 2166 +6 1160 3098 +6 1161 2619 +6 1163 3036 +6 1164 3750 +6 1165 2904 +6 1167 2322 +6 1168 3100 +6 1169 2328 +6 1170 2523 +6 1171 4176 +6 1172 4399 +6 1173 2016 +6 1174 3269 +6 1175 4171 +6 1176 2864 +6 1177 2364 +6 1178 2010 +6 1179 2035 +6 1180 3446 +6 1181 3049 +6 1182 2269 +6 1183 2870 +6 1184 2743 +6 1185 2287 +6 1186 2186 +6 1187 2083 +6 1188 6341 +6 1189 2607 +6 1190 5977 +6 1191 2428 +6 1192 2036 +6 1193 2901 +6 1194 2155 +6 1195 3044 +6 1196 3076 +6 1197 2375 +6 1198 2726 +6 1199 2221 +6 1200 2033 +6 1201 2171 +6 1202 2014 +6 1203 2164 +6 1204 2464 +6 1205 2656 +6 1206 2483 +6 1208 2642 +6 1209 4754 +6 1210 2245 +6 1211 2008 +6 1212 2169 +6 1215 2146 +6 1217 2293 +6 1218 3714 +6 1219 3499 +6 1220 2134 +6 1221 2079 +6 1222 2283 +6 1223 2518 +6 1224 2321 +6 1225 5857 +6 1227 2275 +6 1228 2247 +6 1229 2266 +6 1230 2629 +6 1231 4053 +6 1232 2007 +6 1233 3458 +6 1234 3277 +6 1235 5139 +6 1236 2639 +6 1238 2365 +6 1239 2812 +6 1240 2333 +6 1241 2062 +6 1242 3514 +6 1243 2471 +6 1244 2024 +6 1245 2753 +6 1246 4755 +6 1248 7039 +6 1249 2636 +6 1250 6731 +6 1251 5864 +6 1252 3792 +6 1253 2693 +6 1255 6437 +6 1256 3573 +6 1257 4285 +6 1258 5443 +6 1259 3710 +6 1260 2557 +6 1261 2680 +6 1262 2232 +6 1263 11252 +6 1264 5082 +6 1265 5613 +6 1266 5067 +6 1267 3824 +6 1268 3365 +6 1269 5104 +6 1270 2147 +6 1271 3383 +6 1272 2622 +6 1273 3826 +6 1274 2094 +6 1275 2311 +6 1276 3062 +6 1277 2675 +6 1278 2167 +6 1279 2111 +6 1281 2271 +7 112 12073 +8 112 49781 +8 116 3113 +8 119 20681 +8 121 5648 +8 122 4483 +8 123 3645 +8 127 12434 +8 132 5659 +8 134 13279 +8 136 2314 +8 138 8548 +8 139 5038 +8 142 8713 +8 149 5059 +8 165 8439 +8 187 2376 +8 193 2696 +8 243 2301 +8 359 16960 +8 360 30346 +8 361 3461 +8 368 10942 +8 370 38043 +8 371 2558 +8 372 4067 +8 375 4298 +8 378 2888 +8 380 9394 +8 382 7549 +8 383 4391 +8 393 2088 +8 399 4368 +8 403 2383 +8 405 2227 +8 409 2539 +8 410 3757 +8 414 2344 +8 415 4816 +8 417 5050 +8 421 3960 +8 425 2403 +8 428 12868 +8 436 2590 +8 443 5386 +8 444 2054 +8 446 2016 +8 447 2905 +8 460 2520 +8 464 5599 +8 466 3643 +8 467 2673 +8 470 2331 +8 483 10685 +8 484 3695 +8 491 2933 +8 499 8158 +8 503 4964 +8 511 2771 +8 526 2384 +8 538 2387 +8 544 3118 +8 546 2132 +8 551 3859 +8 553 4981 +8 562 2164 +8 585 3107 +8 628 2124 +8 725 2333 +8 779 2658 +8 785 3466 +8 880 6843 +8 884 7878 +8 914 2800 +8 1031 6823 +9 112 2270 +9 127 17200 +9 132 2266 +10 112 6476 +11 112 4371 +11 359 8277 +12 112 29696 +12 119 28181 +12 121 35001 +12 122 18508 +12 123 6388 +12 127 6730 +12 134 51707 +12 359 48016 +12 360 5536 +12 361 3779 +12 368 3887 +12 380 3136 +12 414 3855 +12 415 6424 +12 428 4219 +12 453 15916 +12 466 8620 +12 483 8228 +12 484 10394 +12 491 6730 +12 551 12962 +12 557 2443 +12 627 2562 +12 628 3110 +12 648 3341 +12 674 7138 +12 698 4922 +12 815 2942 +12 839 4324 +12 1073 2563 +13 112 3705 +14 112 4599 +15 112 31827 +15 113 528707 +15 359 6067 +15 360 9861 +15 368 24752 +15 403 2219 +15 409 6299 +15 410 7447 +15 417 5076 +15 418 2116 +15 428 3657 +15 436 2271 +15 457 6619 +16 112 8190 +16 119 4566 +16 359 4269 +16 360 2887 +16 368 3133 +16 371 2886 +16 375 8906 +16 378 3703 +16 383 3549 +16 387 2354 +16 391 2098 +16 399 7930 +16 405 3543 +16 438 8760 +16 447 2589 +16 466 2076 +16 470 2110 +16 484 8714 +16 495 3595 +16 501 4293 +16 515 2456 +16 516 5356 +16 521 2277 +16 529 3461 +16 543 3237 +16 546 5671 +16 548 2250 +16 564 4030 +16 566 2107 +16 571 6752 +16 583 3546 +16 610 6179 +16 627 2483 +16 628 3684 +16 646 3880 +16 683 4415 +16 772 3662 +16 777 2468 +16 835 3210 +16 864 2867 +17 112 3355 +17 119 7263 +17 359 3701 +17 368 2235 +17 380 2898 +17 383 2239 +17 399 2608 +17 467 2368 +18 112 4577 +18 121 8067 +18 122 44107 +18 123 20924 +18 134 15860 +19 125 9188 +20 112 3487 +20 127 21834 +20 132 3622 +21 121 6932 +21 122 6067 +21 134 14092 +22 128 8122 +22 1092 2604 +23 380 2739 +24 121 4180 +24 122 9125 +24 134 8752 +25 112 7932 +25 595 4105 +25 1216 2046 +26 142 2552 +27 142 7602 +28 142 2941 +28 289 2799 +28 876 11468 +28 922 4574 +28 960 3832 +28 1081 2320 +29 119 2084 +29 360 2786 +30 142 6790 +31 262 2836 +32 142 7107 +33 142 3229 +34 142 2744 +35 138 3175 +35 142 6269 +37 142 3264 +38 112 5144 +38 359 2576 +38 360 2030 +38 365 2965 +38 436 24061 +38 462 3302 +38 490 3727 +38 504 14367 +38 654 3347 +38 1016 2555 +38 1129 3889 +38 1213 2754 +39 112 5199 +39 360 2017 +39 373 22360 +39 383 5454 +39 467 2886 +40 112 5472 +41 112 8707 +42 448 6216 +44 112 9433 +44 118 6205 +44 119 4198 +44 359 5287 +44 360 4072 +44 364 2462 +44 368 3991 +44 378 12100 +44 399 6033 +44 429 2952 +44 466 15050 +44 472 5439 +44 477 4960 +44 531 4264 +44 546 5741 +44 566 6349 +44 571 2977 +44 646 2230 +44 795 5765 +44 864 2684 +44 867 2543 +45 112 4450 +45 119 5526 +45 359 6710 +45 360 12863 +45 368 4357 +45 380 3517 +45 382 2178 +45 428 4113 +45 483 3196 +45 561 2079 +45 717 2992 +46 372 11288 +47 127 3879 +48 538 19206 +49 136 2314 +50 373 2089 +51 119 2895 +51 359 3332 +52 119 2398 +52 359 3647 +52 368 11232 +52 382 6996 +52 396 40224 +52 465 4580 +52 717 5856 +53 372 4876 +56 112 2113 +57 1111 2162 +58 112 3283 +59 112 2634 +59 361 4542 +60 112 5683 +60 360 2406 +60 373 17743 +60 383 2788 +60 593 2375 +61 566 2046 +62 112 4816 +62 428 2077 +63 112 6619 +64 364 2095 +66 36 3975 +66 100 24205 +66 1027 2069 +66 1053 2396 +67 884 5840 +68 891 2394 +68 892 84146 +68 893 2152 +68 913 3595 +69 880 4922 +70 936 2985 +70 937 13224 +70 941 2858 +70 942 2273 +70 943 3390 +70 987 2600 +70 988 2588 +70 1010 2403 +70 1012 3375 +71 891 2356 +72 971 10166 +72 1237 2702 +73 917 2728 +74 885 2083 +75 100 2273 +76 884 5946 +78 970 2183 +79 127 2043 +80 112 8365 +81 1031 2348 +83 1131 2735 +84 648 3050 +85 1149 2029 +85 1150 3096 +87 1030 2240 +98 127 4107 diff --git a/shiny/observatory/uj_business.rdata b/shiny/observatory/uj_business.rdata new file mode 100644 index 0000000..9d930b5 --- /dev/null +++ b/shiny/observatory/uj_business.rdata @@ -0,0 +1,323 @@ +*Vertices 256 +*Arcs +1 45 9296 +1 46 277 +1 47 1841 +1 49 2382 +1 50 136 +1 51 123 +1 52 30 +1 53 468 +1 54 485 +1 55 509 +1 56 135 +1 57 4558 +1 58 684 +1 60 62 +1 61 128 +1 62 292 +1 63 682 +1 64 254 +1 65 78 +1 66 110 +1 67 134 +1 69 47 +1 70 114 +1 71 466 +1 72 157 +1 73 198 +1 74 14595 +1 75 98 +1 76 79 +1 77 357 +1 78 76 +1 79 770 +1 80 73 +1 81 185 +1 84 55 +1 85 113 +1 86 116 +1 87 53 +1 88 279 +1 89 240 +1 90 43 +1 91 78 +1 92 52 +1 95 191 +1 96 62 +1 97 49 +1 98 31 +1 99 121 +1 100 27 +1 101 275 +1 103 84 +1 104 113 +1 105 77 +1 107 52 +1 108 151 +1 110 360 +1 111 193 +1 112 62 +1 114 33 +1 119 143 +1 120 148 +1 124 88 +1 126 78 +1 127 54 +1 128 26 +1 129 43 +1 130 84 +1 131 127 +1 132 143 +1 133 92 +1 135 80 +1 136 42 +1 137 87 +1 138 33 +1 140 144 +1 142 232 +1 145 372 +1 147 34 +1 148 39 +1 154 131 +1 161 29 +1 166 36 +1 171 32 +1 172 33 +1 173 63 +1 176 86 +1 178 30 +1 179 63 +1 180 72 +1 182 38 +1 184 28 +1 185 96 +1 186 38 +1 199 33 +1 201 27 +1 202 41 +1 203 54 +1 204 26 +1 205 30 +1 206 34 +1 207 33 +1 210 58 +1 212 46 +1 218 28 +1 219 59 +1 221 49 +1 224 77 +1 239 43 +1 243 32 +1 246 36 +1 248 30 +1 249 42 +1 250 27 +1 251 28 +1 256 32 +2 45 455 +2 47 183 +2 48 201 +2 49 188 +2 53 46 +2 54 75 +2 55 38 +2 57 319 +2 58 54 +2 59 93 +2 62 64 +2 63 184 +2 68 70 +2 74 286 +2 82 30 +2 83 84 +2 88 44 +2 92 986 +2 93 44 +2 94 106 +2 101 42 +2 106 26 +2 109 59 +2 113 281 +2 115 27 +2 116 65 +2 117 477 +2 118 40 +2 121 26 +2 122 48 +2 123 49 +2 125 53 +2 132 33 +2 134 95 +2 139 534 +2 141 34 +2 143 52 +2 144 246 +2 146 310 +2 149 37 +2 150 51 +2 151 27 +2 152 198 +2 153 257 +2 154 26 +2 155 103 +2 156 170 +2 157 224 +2 158 125 +2 159 100 +2 160 232 +2 161 412 +2 162 214 +2 163 106 +2 164 48 +2 165 129 +2 166 278 +2 167 73 +2 168 51 +2 169 32 +2 170 85 +2 174 148 +2 177 193 +2 183 38 +2 187 36 +2 188 31 +2 189 208 +2 190 28 +2 191 26 +2 192 57 +2 193 60 +2 194 36 +2 195 127 +2 196 143 +2 197 55 +2 198 38 +2 200 28 +2 208 89 +2 209 61 +2 211 37 +2 213 34 +2 214 42 +2 215 62 +2 216 26 +2 217 41 +2 220 37 +2 222 30 +2 223 32 +2 225 62 +2 226 26 +2 227 62 +2 228 46 +2 229 31 +2 230 33 +2 231 53 +2 232 30 +2 233 30 +2 234 33 +2 235 36 +2 236 42 +2 237 47 +2 240 27 +2 241 35 +2 244 29 +2 245 77 +2 247 46 +2 252 26 +2 253 26 +2 254 29 +2 255 30 +3 45 732 +3 47 318 +3 49 308 +3 53 47 +3 54 186 +3 55 98 +3 57 415 +3 58 114 +3 60 28 +3 62 99 +3 63 210 +3 66 39 +3 70 193 +3 72 43 +3 74 582 +3 77 30 +3 88 164 +3 89 79 +3 91 33 +3 95 44 +3 102 519 +3 103 53 +3 104 28 +3 108 57 +3 110 28 +3 111 35 +3 124 28 +3 131 68 +3 132 95 +3 135 65 +3 137 29 +3 142 43 +3 145 57 +3 154 26 +3 173 34 +3 238 34 +4 62 33 +4 73 53 +4 85 37 +5 67 114 +6 45 35 +7 55 708 +8 45 26 +8 74 29 +9 70 66 +10 85 69 +11 47 145 +12 74 34 +13 45 408 +13 57 32 +14 45 231 +14 57 232 +15 45 461 +15 57 55 +16 77 32 +17 45 211 +17 57 33 +17 74 181 +18 57 133 +19 132 42 +19 135 50 +20 74 76 +21 132 43 +22 45 171 +22 57 82 +22 74 295 +22 79 31 +22 131 38 +22 145 26 +23 45 98 +24 181 86 +24 242 40 +25 45 70 +25 74 30 +26 120 61 +27 74 116 +28 45 175 +29 57 51 +30 57 77 +31 58 34 +31 62 35 +31 85 115 +32 73 26 +33 85 37 +34 175 31 +35 55 31 +36 49 72 +37 67 103 +38 57 28 +39 57 50 +40 57 36 +41 47 29 +42 132 73 +42 135 35 +43 57 46 +44 47 26 diff --git a/shiny/observatory/userjourneys.R b/shiny/observatory/userjourneys.R index 040d41c..6fe5a0c 100644 --- a/shiny/observatory/userjourneys.R +++ b/shiny/observatory/userjourneys.R @@ -1,27 +1,53 @@ +ujig.copy <- read.graph("uj_all.rdata", format = "pajek") +ujbusiness.copy <- read.graph("uj_business.rdata", format = "pajek") + userJourneys <- tabPanel( - "User Journeys", # Sidebar with a slider input for number of bins + "Cross-site User Journeys", # Sidebar with a slider input for number of bins # Sidebar layout with input and output definitions ---- sidebarLayout( # Sidebar panel for inputs ---- sidebarPanel( - sliderInput("bar_steps", label = "Steps:", - min = 1, max = 6, value = 6, step = 1), - sliderInput("bar_journeys", label = "Journeys:", - min = 1, max = 6, value = 5, step = 1) - ) - , + # Input: Selector for choosing dataset ---- + selectInput( + inputId = "journeys", + label = "Choose a life event journey:", + choices = c("business", "all") + ), + width = 3 ), # Main panel for displaying outputs ---- main = mainPanel( -d3Output("d3", width = "100%", height = 800) - ) + # Output: Formatted text for caption ---- + h3(textOutput("uj-caption", container = span)), + # Output: Verbatim text for data summary ---- + verbatimTextOutput("uj-summary"), + # Output: HTML table with requested number of observations ---- + fluidRow(forceNetworkOutput("force"))) ) ) + userjourneys_server <- function (input, output) { - output$d3 <- renderD3({ - r2d3( - replicate(input$bar_journeys, list(data.frame(title = replicate(input$bar_steps,"")))), - script = "userjourneys.js" - ) + dataSet <- reactive({ + switch(input$journeys, + "all" = ujig.copy, + "business"= ujbusiness.copy)}) + + wc <- reactive({cluster_walktrap(dataSet())}) + members <- reactive({membership(wc())}) + + graph_data <- reactive({igraph_to_networkD3(dataSet(), group = members())}) + + output$uj_caption <- renderText({ + paste("Showing ",input$journeys, " life event journeys across .gov.au from May 1 2019 - May 15 2019") + }) + + + output$force <- renderForceNetwork({ + forceNetwork(Links = graph_data()$links, Nodes = graph_data()$nodes, + Source = "source", Target = "target", + Value = "value", NodeID = "name", + Group = "group", zoom = TRUE, linkWidth = (graph_data()$links$value)/500, opacity = .4) }) } + +shinyApp(ui = userJourneys, server = userjourneys_server) diff --git a/shiny/observatory/userjourneys.js b/shiny/observatory/userjourneys.js deleted file mode 100644 index 93fe888..0000000 --- a/shiny/observatory/userjourneys.js +++ /dev/null @@ -1,80 +0,0 @@ -// !preview r2d3 data=list(data.frame(title = c("","","")), data.frame(title = c("","",""))),height=800 -// -// r2d3: https://rstudio.github.io/r2d3 -// - -r2d3.svg.selectAll("svg > *").remove(); -var g = r2d3.svg.selectAll() - .data(data) - .enter() - .append("g") - .attr("transform", function(d, i) {return "translate(" + 10 + "," + (i*140) + ")"}); - -function dx(d,i) { - return (i * 125) + 50; -} -function dy(d,i) { - return 90; -} -var lineFunction = d3.line() - .x(function(d,i) {return dx(d,i)}) - .y(function(d,i) {return dy(d,i)}) - .curve(d3.curveLinear); -var line = g.append("path") - .attr("d", function(d) {return lineFunction(d.title)}) - .attr("stroke", "grey") - .attr("stroke-width", 20) - .attr("fill", "white"); - -var circles = g.selectAll().data(function (d) { - return HTMLWidgets.dataframeToD3(d) -}); -circles.enter() - .append('circle') - .attr("cy", function(d,i) {return dy(d,i)}) - .attr("cx", function(d,i) {return dx(d,i)}) - .attr('r',30) - .attr('fill', 'white') - .attr('stroke', 'grey') - .attr('stroke-width','20px') - ; - -function wrap(text, width) { - // https://stackoverflow.com/questions/24784302/wrapping-text-in-d3 - text.each(function () { - var text = d3.select(this), - words = text.text().split(/\s+/).reverse(), - word, - line = [], - lineNumber = 0, - lineHeight = 1.1, // ems - x = text.attr("x"), - y = text.attr("y"), - dy = 0, //parseFloat(text.attr("dy")), - tspan = text.text(null) - .append("tspan") - .attr("x", x) - .attr("y", y) - .attr("dy", dy + "em"); - while (word = words.pop()) { - line.push(word); - tspan.text(line.join(" ")); - if (tspan.node().getComputedTextLength() > width) { - line.pop(); - tspan.text(line.join(" ")); - line = [word]; - tspan = text.append("tspan") - .attr("x", x) - .attr("y", y) - .attr("dy", ++lineNumber * lineHeight + dy + "em") - .text(word); - } - } - }); -} -var texts = g.selectAll().data(function(d) { return d.title}).enter().append("text") - .text(function(d) { return d }) - .style("font-size", function(d,i) { return Math.min(20, dy(d,i)/ this.getComputedTextLength() * 20) + "px"; }) - .attr("dx", function(d,i) {return dx(d,i)-this.getComputedTextLength()/2}) - .attr("dy", "160px"); - diff --git a/shiny/observatory/www/designsystem.min.css b/shiny/observatory/www/designsystem.min.css index 3407578..131288a 100644 --- a/shiny/observatory/www/designsystem.min.css +++ b/shiny/observatory/www/designsystem.min.css @@ -22,6 +22,6 @@ body { box-shadow: 0px 51px 0px #313131 inset; } html { - font-size: 15px; + font-size: 15px !important; } } diff --git a/shiny/observatory/www/theme.css b/shiny/observatory/www/theme.css index babfe64..c584d8c 100644 --- a/shiny/observatory/www/theme.css +++ b/shiny/observatory/www/theme.css @@ -1069,7 +1069,7 @@ th { box-sizing: border-box; } html { - font-size: 10px; + font-size: 16px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } body { diff --git a/tools/warcraider/.idea/misc.xml b/tools/warcraider/.idea/misc.xml deleted file mode 100644 index 0ecb5c3..0000000 --- a/tools/warcraider/.idea/misc.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/tools/warcraider/.idea/modules.xml b/tools/warcraider/.idea/modules.xml deleted file mode 100644 index 6fe7de2..0000000 --- a/tools/warcraider/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/tools/warcraider/.idea/vcs.xml b/tools/warcraider/.idea/vcs.xml deleted file mode 100644 index b2bdec2..0000000 --- a/tools/warcraider/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/tools/warcraider/.idea/warcraider.iml b/tools/warcraider/.idea/warcraider.iml deleted file mode 100644 index b7b4242..0000000 --- a/tools/warcraider/.idea/warcraider.iml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/tools/warcraider/.idea/workspace.xml b/tools/warcraider/.idea/workspace.xml deleted file mode 100644 index 8f65ea1..0000000 --- a/tools/warcraider/.idea/workspace.xml +++ /dev/null @@ -1,213 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -