Spaces:
Running
Running
Upload 82 files
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- .gitattributes +6 -0
- README.md +16 -8
- app.py +284 -0
- not_used_Dockerfile +21 -0
- requirements.txt +8 -0
- runtime.txt +1 -0
- src/annotation/setP11.sh +37 -0
- src/arborator-draft/ArboratorDraft.js +1 -0
- src/arborator-draft/FileSaver.min.js +3 -0
- src/arborator-draft/arborator-draft.css +250 -0
- src/arborator-draft/arborator-draft.js +691 -0
- src/arborator-draft/arborator-draft2.css +118 -0
- src/arborator-draft/arborator-draft2.js +720 -0
- src/arborator-draft/arborator.svg +27 -0
- src/arborator-draft/bootstrap.min.css +0 -0
- src/arborator-draft/canvg.js +0 -0
- src/arborator-draft/d3.js +0 -0
- src/arborator-draft/example_arborator-draft.html +198 -0
- src/arborator-draft/jquery-3.2.1.min.js +4 -0
- src/arborator-draft/jszip.min.js +13 -0
- src/arborator-draft/speedtest.oneBigConllTag.html +0 -0
- src/arborator-draft/speedtest.separateConllTags.html +0 -0
- src/evalatin2024-latinpipe/LICENSE +373 -0
- src/evalatin2024-latinpipe/README.md +118 -0
- src/evalatin2024-latinpipe/__pycache__/latinpipe_evalatin24_eval.cpython-311.pyc +0 -0
- src/evalatin2024-latinpipe/data/conllu_split.py +39 -0
- src/evalatin2024-latinpipe/data/fetch_data.sh +66 -0
- src/evalatin2024-latinpipe/figures/LatinPipe.svg +0 -0
- src/evalatin2024-latinpipe/latinpipe-evalatin24-240520/LICENSE +435 -0
- src/evalatin2024-latinpipe/latinpipe-evalatin24-240520/README.md +71 -0
- src/evalatin2024-latinpipe/latinpipe_evalatin24.py +944 -0
- src/evalatin2024-latinpipe/latinpipe_evalatin24_eval.py +596 -0
- src/evalatin2024-latinpipe/latinpipe_evalatin24_server.py +433 -0
- src/evalatin2024-latinpipe/parsed.conllu +20 -0
- src/evalatin2024-latinpipe/requirements.txt +8 -0
- src/img/c4ia.png +0 -0
- src/img/icmc.png +3 -0
- src/img/inova_nobackground.png +0 -0
- src/img/mcti_nobackground.png +0 -0
- src/img/motorola_nobackground.png +0 -0
- src/img/nilc-removebg.png +0 -0
- src/img/softex_nobackground.png +0 -0
- src/img/wordcloud_brasil5.png +3 -0
- src/portSentencer/abbrev.txt +397 -0
- src/portSentencer/portSent.py +242 -0
- src/portTokenizer/ADJ.tsv +0 -0
- src/portTokenizer/ADP.tsv +38 -0
- src/portTokenizer/ADV.tsv +0 -0
- src/portTokenizer/AUX.tsv +435 -0
- src/portTokenizer/CCONJ.tsv +25 -0
.gitattributes
CHANGED
|
@@ -33,3 +33,9 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
| 36 |
+
src/img/icmc.png filter=lfs diff=lfs merge=lfs -text
|
| 37 |
+
src/img/wordcloud_brasil5.png filter=lfs diff=lfs merge=lfs -text
|
| 38 |
+
src/portTokenizer/VERB.tsv filter=lfs diff=lfs merge=lfs -text
|
| 39 |
+
src/portTokenizer/WORDmaster.txt filter=lfs diff=lfs merge=lfs -text
|
| 40 |
+
src/postproc/VERB.tsv filter=lfs diff=lfs merge=lfs -text
|
| 41 |
+
src/postproc/WORDmaster.txt filter=lfs diff=lfs merge=lfs -text
|
README.md
CHANGED
|
@@ -1,15 +1,23 @@
|
|
| 1 |
---
|
| 2 |
title: Portparser.v2
|
| 3 |
-
emoji:
|
| 4 |
-
colorFrom:
|
| 5 |
-
colorTo:
|
| 6 |
sdk: streamlit
|
| 7 |
-
|
| 8 |
-
|
|
|
|
|
|
|
| 9 |
pinned: false
|
| 10 |
-
|
| 11 |
-
|
|
|
|
| 12 |
python_version: 3.11
|
| 13 |
---
|
| 14 |
|
| 15 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
---
|
| 2 |
title: Portparser.v2
|
| 3 |
+
emoji: 📚
|
| 4 |
+
colorFrom: red
|
| 5 |
+
colorTo: red
|
| 6 |
sdk: streamlit
|
| 7 |
+
app_port: 8501
|
| 8 |
+
tags:
|
| 9 |
+
- Universal Dependencies
|
| 10 |
+
- Portuguese
|
| 11 |
pinned: false
|
| 12 |
+
short_description: Parser for Portuguese texts using UD standards
|
| 13 |
+
license: cc-by-4.0
|
| 14 |
+
sdk_version: 1.46.1
|
| 15 |
python_version: 3.11
|
| 16 |
---
|
| 17 |
|
| 18 |
+
# Welcome to Streamlit!
|
| 19 |
+
|
| 20 |
+
Edit `app.py` to customize this app to your heart's desire. :heart:
|
| 21 |
+
|
| 22 |
+
If you have any questions, checkout our [documentation](https://docs.streamlit.io) and [community
|
| 23 |
+
forums](https://discuss.streamlit.io).
|
app.py
ADDED
|
@@ -0,0 +1,284 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import sys, os, datetime, random, base64, time
|
| 2 |
+
import streamlit as st
|
| 3 |
+
import streamlit.components.v1 as components
|
| 4 |
+
from tempfile import mkdtemp
|
| 5 |
+
from pathlib import Path
|
| 6 |
+
import pandas as pd
|
| 7 |
+
from huggingface_hub import hf_hub_download
|
| 8 |
+
|
| 9 |
+
#-----Initial Parameters----
|
| 10 |
+
|
| 11 |
+
# Must be always False in production. When DEBUG is set to True the interface do not call the parser. Mode to debug interface features in local development.
|
| 12 |
+
DEBUG=False
|
| 13 |
+
# Embedding model. Options are: 'bert-base-portuguese-cased' or 'bert-base-multilingual-uncased'
|
| 14 |
+
MODEL='bert-base-portuguese-cased'
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
#-----Fuctions-----
|
| 18 |
+
|
| 19 |
+
# Format external files for interface compatibility
|
| 20 |
+
def img_to_bytes(img_path):
|
| 21 |
+
img_bytes = Path(img_path).read_bytes()
|
| 22 |
+
encoded = base64.b64encode(img_bytes).decode()
|
| 23 |
+
return encoded
|
| 24 |
+
|
| 25 |
+
def img_to_html(img_path, img_style='max-width: 100%;'):
|
| 26 |
+
img_html = f"<img src='data:image/png;base64,{img_to_bytes(img_path)}' style='{img_style}'>"
|
| 27 |
+
return img_html
|
| 28 |
+
|
| 29 |
+
# Call parser steps
|
| 30 |
+
def make_sentences(path_raw_text, path_text):
|
| 31 |
+
try:
|
| 32 |
+
#st.text(f'python ./src/portSentencer/portSent.py -o {path_text} -r -l 2048 {path_raw_text}')
|
| 33 |
+
outcome = os.system(f'python ./src/portSentencer/portSent.py -o {path_text} -r -l 2048 {path_raw_text}')
|
| 34 |
+
return f'S'+str(outcome)
|
| 35 |
+
except Exception as e:
|
| 36 |
+
return str(e)
|
| 37 |
+
|
| 38 |
+
def make_conllu(path_text, path_empty_conllu):
|
| 39 |
+
try:
|
| 40 |
+
outcome = os.system(f'python ./src/portTokenizer/portTok.py -o {path_empty_conllu} -m -s S0000 {path_text}')
|
| 41 |
+
return 'T'+str(outcome)
|
| 42 |
+
except Exception as e:
|
| 43 |
+
return str(e)
|
| 44 |
+
|
| 45 |
+
def make_pred(path_empty_conllu, target_directory, model):
|
| 46 |
+
try:
|
| 47 |
+
outcome = os.system(f'python ./src/evalatin2024-latinpipe/latinpipe_evalatin24.py --load {model} --exp {target_directory} --test {path_empty_conllu}')
|
| 48 |
+
return f'P'+str(outcome)
|
| 49 |
+
except Exception as e:
|
| 50 |
+
return str(e)
|
| 51 |
+
|
| 52 |
+
def make_postproc(path_predicted_conllu, path_final_conllu):
|
| 53 |
+
try:
|
| 54 |
+
outcome = os.system(f'python ./src/postproc/postprocess.py -o {path_final_conllu} {path_predicted_conllu}')
|
| 55 |
+
return f'F'+str(outcome)
|
| 56 |
+
except Exception as e:
|
| 57 |
+
return str(e)
|
| 58 |
+
|
| 59 |
+
def get_predictions(path_prediction):
|
| 60 |
+
try:
|
| 61 |
+
with open(path_prediction, 'r') as f:
|
| 62 |
+
st.text(f.read())
|
| 63 |
+
except Exception as e:
|
| 64 |
+
st.text('Resposta: '+e)
|
| 65 |
+
|
| 66 |
+
|
| 67 |
+
def run_pipeline(tmp_dir,code):
|
| 68 |
+
|
| 69 |
+
path_text = tmp_dir+"/"+code+"_input.txt"
|
| 70 |
+
path_empty_conllu = tmp_dir+"/"+code+"_input.conllu"
|
| 71 |
+
#path_predicted_annot = './src/annotation/'+code+'_input.predicted.conllu'
|
| 72 |
+
path_predicted_conllu = tmp_dir+"/"+code+"_input.predicted.conllu"
|
| 73 |
+
path_final_conllu = tmp_dir+"/"+code+"_parsed.conllu"
|
| 74 |
+
#model = '../Portparser.v2-latinpipe-core/model.weights.h5'
|
| 75 |
+
model = hf_hub_download(repo_id="lucelene/Portparser.v2-latinpipe-core",
|
| 76 |
+
filename="model.weights.h5",
|
| 77 |
+
repo_type="model")
|
| 78 |
+
model_op = hf_hub_download(repo_id="lucelene/Portparser.v2-latinpipe-core",
|
| 79 |
+
filename="options.json",
|
| 80 |
+
repo_type="model")
|
| 81 |
+
model_mks = hf_hub_download(repo_id="lucelene/Portparser.v2-latinpipe-core",
|
| 82 |
+
filename="mappings.pkl",
|
| 83 |
+
repo_type="model")
|
| 84 |
+
print("links", model, model_op)
|
| 85 |
+
|
| 86 |
+
# with st.spinner(f'Tok {path_text} into {path_empty_conllu}'):
|
| 87 |
+
with st.spinner('Generating CoNLL-U...'):
|
| 88 |
+
#time.sleep(1)
|
| 89 |
+
try:
|
| 90 |
+
outcome = make_conllu(path_text, path_empty_conllu)
|
| 91 |
+
#st.write("Tok executou!")
|
| 92 |
+
#time.sleep(10)
|
| 93 |
+
except Exception as e:
|
| 94 |
+
st.write("Tok: "+e)
|
| 95 |
+
time.sleep(10)
|
| 96 |
+
# with st.spinner(f'{outcome} - Pred {path_empty_conllu} with {model} into {path_predicted_conllu}'):
|
| 97 |
+
with st.spinner('Predicting annotation...'):
|
| 98 |
+
#time.sleep(1)
|
| 99 |
+
try:
|
| 100 |
+
outcome = make_pred(path_empty_conllu, tmp_dir, model)
|
| 101 |
+
#st.write("Pred executou!")
|
| 102 |
+
#time.sleep(10)
|
| 103 |
+
except Exception as e:
|
| 104 |
+
st.write("Pred: "+e)
|
| 105 |
+
time.sleep(10)
|
| 106 |
+
#infile = open(path_predicted_conllu, "r")
|
| 107 |
+
#empFile = infile.read()
|
| 108 |
+
#infile.close()
|
| 109 |
+
#with st.spinner(path_predicted_conllu+"\n"+empFile):
|
| 110 |
+
#time.sleep(10)
|
| 111 |
+
# with st.spinner(f'{outcome} - Post {path_predicted_conllu} into {path_final_conllu}'):
|
| 112 |
+
with st.spinner('Postprocessing...'):
|
| 113 |
+
#time.sleep(1)
|
| 114 |
+
try:
|
| 115 |
+
outcome = make_postproc(path_predicted_conllu, path_final_conllu)
|
| 116 |
+
#st.write("Postp executou!")
|
| 117 |
+
#time.sleep(10)
|
| 118 |
+
except Exception as e:
|
| 119 |
+
st.write("Postp: "+e)
|
| 120 |
+
time.sleep(10)
|
| 121 |
+
# with st.spinner(f'{outcome} - Done at {path_final_conllu}'):
|
| 122 |
+
with st.spinner('Parsed!'):
|
| 123 |
+
#infile = open(path_final_conllu, "r")
|
| 124 |
+
#empFile = infile.read()
|
| 125 |
+
#infile.close()
|
| 126 |
+
time.sleep(1)
|
| 127 |
+
return path_final_conllu
|
| 128 |
+
|
| 129 |
+
#-----Main Stuff-----
|
| 130 |
+
print("Running the HF server...")
|
| 131 |
+
print(f"Python version: {sys.version_info.major}.{sys.version_info.minor}")
|
| 132 |
+
tmp_dir = mkdtemp()
|
| 133 |
+
#print(tmp_dir)
|
| 134 |
+
code = f'{datetime.datetime.now().strftime("%d%m%Y_%H%M%S%f")+"_"+str(random.randint(0, 9))}'
|
| 135 |
+
#print(code)
|
| 136 |
+
work_dir = './temp/'
|
| 137 |
+
os.chdir('.')
|
| 138 |
+
path_text = f'{tmp_dir}/{code}_input.txt'
|
| 139 |
+
path_final_conllu = f'{work_dir}parsed.conllu' # default to display
|
| 140 |
+
area=0
|
| 141 |
+
with open(path_final_conllu, 'r', encoding='utf-8') as f:content = f.read().split('\n')
|
| 142 |
+
|
| 143 |
+
#-----Interface-----
|
| 144 |
+
with open('./src/arborator-draft/arborator-draft.css','rb') as f: arborator_css = f.read().decode()
|
| 145 |
+
with open('./src/style.css') as f: css = f.read()
|
| 146 |
+
|
| 147 |
+
st.set_page_config(page_title='Portparser v.2', layout="wide")
|
| 148 |
+
st.markdown(f'<style>{css}</style>', unsafe_allow_html=True)
|
| 149 |
+
|
| 150 |
+
# Grid
|
| 151 |
+
rowall = st.columns([2,26,2])
|
| 152 |
+
with rowall[1]:
|
| 153 |
+
row2 = st.columns([6,4])
|
| 154 |
+
# Head
|
| 155 |
+
with row2[0]:
|
| 156 |
+
st.markdown("<p id='logo-position'><b id='logo-title'><i>Portparser</i></b><b id='logo-version'>v.2</b><br><b id='logo-subtitle'>A parsing model for Brazilian Portuguese</b></p>",unsafe_allow_html=True)
|
| 157 |
+
st.markdown("<p class='text'> This is Portparser, a parsing model for Brazilian Portuguese that follows the <a href='https://universaldependencies.org/'>Universal Dependencies (UD)</a> framework.\
|
| 158 |
+
We built our model by using a recently released manually annotated corpus, the Porttinari-base, \
|
| 159 |
+
and we explored different parsing methods and parameters for training. We also test multiple embedding models and parsing methods. \
|
| 160 |
+
Portparser is the result of the best combination achieved in our experiments.</p><p class='text'>This model (version 2) is an evolution of the work previously reported \
|
| 161 |
+
by <a href='https://aclanthology.org/2024.propor-1.41/'>Lopes and Pardo (2024)</a>, and all datasets and full instructions to reproduce our experiments are\
|
| 162 |
+
freely available at the <a href='https://github.com/LuceleneL/Portparser.v2'>Portparser v2 repository</a>. More details about this work may also be found at \
|
| 163 |
+
the <a href='https://sites.google.com/icmc.usp.br/poetisa'>POeTiSA project webpage</a>.</p>",unsafe_allow_html=True)
|
| 164 |
+
with st.expander('To cite Portparser', expanded=False):
|
| 165 |
+
st.code("""
|
| 166 |
+
@inproceedings{lopes2024towards,
|
| 167 |
+
title={Towards Portparser-a highly accurate parsing system for Brazilian Portuguese following the Universal Dependencies framework},
|
| 168 |
+
author={Lopes, Lucelene and Pardo, Thiago},
|
| 169 |
+
booktitle={Proceedings of the 16th International Conference on Computational Processing of Portuguese},
|
| 170 |
+
pages={401--410},
|
| 171 |
+
year={2024}
|
| 172 |
+
}""")
|
| 173 |
+
with row2[1]:
|
| 174 |
+
st.markdown(img_to_html('./src/img/wordcloud_brasil5.png','width:100%; object-position: center top;'), unsafe_allow_html=True)
|
| 175 |
+
# Mode to parse sentence
|
| 176 |
+
mode1, mode2 = st.tabs(['Single sentence', 'Multiple sentences'])
|
| 177 |
+
# 'Single sentence'
|
| 178 |
+
with mode1:
|
| 179 |
+
rowmode1 = st.columns([1,28,1])
|
| 180 |
+
with rowmode1[1]:
|
| 181 |
+
st.write('Write a sentence and run to parse:')
|
| 182 |
+
with st.form("parser"):
|
| 183 |
+
text = st.text_input('Text: ')+' '
|
| 184 |
+
#print("TEXTO",text,"TEXTO")
|
| 185 |
+
#model_selected = MODEL+'-last4'
|
| 186 |
+
submit = st.form_submit_button('Run')
|
| 187 |
+
tab3, tab2, tab1 = st.tabs(["Tree","Table","CoNLL-U"])
|
| 188 |
+
#with open(path_prediction, 'r', encoding='utf-8') as f: content = f.read()
|
| 189 |
+
if submit:
|
| 190 |
+
if not text.strip(): st.text("Can not parse empty text. Write a text above to parse.")
|
| 191 |
+
else:
|
| 192 |
+
try:
|
| 193 |
+
with open(path_text,'w',encoding='utf-8') as f: f.write(text)
|
| 194 |
+
if not DEBUG: path_final_conllu = run_pipeline(tmp_dir,code)
|
| 195 |
+
area=650
|
| 196 |
+
with open(path_final_conllu, 'r', encoding='utf-8') as f:
|
| 197 |
+
content = f.read()
|
| 198 |
+
tab1.text(content)
|
| 199 |
+
content = content.split('\n')
|
| 200 |
+
table = pd.DataFrame([line.split('\t') for line in content[4:]])
|
| 201 |
+
table.columns = ['ID','FORM','LEMMA','UPOS','XPOS','FEATS','HEAD','DEPREL','DEPS','MISC']
|
| 202 |
+
tab2.dataframe(table[:-2], use_container_width=True,hide_index=True)
|
| 203 |
+
except Exception as e:
|
| 204 |
+
st.text('Não deu certo a predição.'+str(e)+repr(e))
|
| 205 |
+
with tab3:
|
| 206 |
+
# Prepare UD tree
|
| 207 |
+
content_str = '\n'.join(content)
|
| 208 |
+
components.html(
|
| 209 |
+
'<style>'+open('./src/arborator-draft/arborator-draft.css','rb').read().decode()+'</style>'+
|
| 210 |
+
#'<style>{arborator_css}</style>'+
|
| 211 |
+
"""
|
| 212 |
+
<script language="JavaScript" type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.js"></script>
|
| 213 |
+
<script src="https://code.jquery.com/jquery-3.2.1.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"></script>
|
| 214 |
+
"""+
|
| 215 |
+
'<script>'+open('./src/arborator-draft/arborator-draft.js','rb').read().decode()+'</script>'+
|
| 216 |
+
f'<conll>{content_str}</conll>'+
|
| 217 |
+
'<script>new ArboratorDraft();</script>',height=area)
|
| 218 |
+
|
| 219 |
+
# 'Multiple sentences'
|
| 220 |
+
with mode2:
|
| 221 |
+
rowmode2 = st.columns([1,13,1,14,1])
|
| 222 |
+
predictions = False
|
| 223 |
+
with rowmode2[3]:
|
| 224 |
+
explanation = 'Upload a text file in order to parse multiple sentences. The file must be in a txt format with one sentence per line. \
|
| 225 |
+
In case you have multiple sentences altogether, first select the option "Segment text for me" below, and we split it in lines for you.'
|
| 226 |
+
option1, option2 = 'Text is ready (one sentence per line)','Segment text for me'
|
| 227 |
+
split_option = st.radio(explanation,[option1,option2])
|
| 228 |
+
with rowmode2[1]:
|
| 229 |
+
with st.form("uploadfile_parser"):
|
| 230 |
+
uploaded_file = st.file_uploader("Choose a file")
|
| 231 |
+
submit = st.form_submit_button('Run')
|
| 232 |
+
if submit:
|
| 233 |
+
if uploaded_file is not None:
|
| 234 |
+
# Segment text first
|
| 235 |
+
if split_option==option2:
|
| 236 |
+
path_raw_text = path_text[:-4]+'_raw.txt'
|
| 237 |
+
with open(path_raw_text, 'w') as f: f.write(uploaded_file.read().decode('utf-8'))
|
| 238 |
+
outcome = make_sentences(path_raw_text, path_text)
|
| 239 |
+
# Do not segment text first
|
| 240 |
+
else:
|
| 241 |
+
with open(path_text,'w', encoding="utf-8") as f:f.write(uploaded_file.read().decode('utf-8')+' ')
|
| 242 |
+
if not DEBUG: path_final_conllu = run_pipeline(tmp_dir,code)
|
| 243 |
+
st.download_button(
|
| 244 |
+
label="Download predictions",
|
| 245 |
+
data=open(path_final_conllu, 'r', encoding='utf-8').read(),
|
| 246 |
+
file_name='portparser_generated.conllu')
|
| 247 |
+
predictions = True
|
| 248 |
+
else:
|
| 249 |
+
st.text('Submit a text file to parse.')
|
| 250 |
+
if predictions:
|
| 251 |
+
row1mode2 = st.columns([1,28,1])
|
| 252 |
+
with row1mode2[1]:
|
| 253 |
+
tab1mode2, tab2mode2 = st.tabs(["Sentences","CoNLL-U"])
|
| 254 |
+
tab1mode2.text(open(path_text,"r").read())
|
| 255 |
+
tab2mode2.text(open(path_final_conllu,"r").read())
|
| 256 |
+
|
| 257 |
+
# Foot
|
| 258 |
+
with st.container():
|
| 259 |
+
logorow1 = st.columns([7,4,1,4,1,4,7])
|
| 260 |
+
with logorow1[1]:
|
| 261 |
+
st.markdown("<a href='https://www.icmc.usp.br/'>"+img_to_html('./src/img/icmc.png')+"</a>",unsafe_allow_html=True)
|
| 262 |
+
with logorow1[3]:
|
| 263 |
+
st.markdown("<a href='https://c4ai.inova.usp.br/pt/inicio/'>"+img_to_html('./src/img/c4ia.png')+"</a>",unsafe_allow_html=True)
|
| 264 |
+
with logorow1[5]:
|
| 265 |
+
st.markdown("<a href='https://sites.google.com/view/nilc-usp/'>"+img_to_html('./src/img/nilc-removebg.png','max-width:80%')+"</a>",unsafe_allow_html=True)
|
| 266 |
+
logorow2 = st.columns([7,4,1,4,1,5,7])
|
| 267 |
+
with logorow2[1]:
|
| 268 |
+
st.markdown("<a href='https://inova.usp.br/'>"+img_to_html('./src/img/inova_nobackground.png')+"</a>",unsafe_allow_html=True)
|
| 269 |
+
with logorow2[3]:
|
| 270 |
+
st.markdown("<a href='https://softex.br/'>" + img_to_html('./src/img/softex_nobackground.png') + "</a>",unsafe_allow_html=True)
|
| 271 |
+
with logorow2[5]:
|
| 272 |
+
st.markdown("<a href='https://www.gov.br/mcti/pt-br'>" + img_to_html('./src/img/mcti_nobackground.png') + "</a>",unsafe_allow_html=True)
|
| 273 |
+
logorow3 = st.columns([7,4,1,4,1,4,7])
|
| 274 |
+
with logorow3[3]:
|
| 275 |
+
st.markdown("<a href='https://www.motorola.com.br/'>"+img_to_html('./src/img/motorola_nobackground.png', 'max-width:70%; object-position: center bottom')+"</a>",unsafe_allow_html=True)
|
| 276 |
+
creditrow = st.columns([7,14,7])
|
| 277 |
+
with creditrow[1]:
|
| 278 |
+
st.markdown('<p style="text-align: center;margin-top:10px"> Developed by Lucelene Lopes\
|
| 279 |
+
<a href="https://github.com/LuceleneL"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-github" viewBox="0 0 16 16">\
|
| 280 |
+
<path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27s1.36.09 2 .27c1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.01 8.01 0 0 0 16 8c0-4.42-3.58-8-8-8"/>\
|
| 281 |
+
</svg></i></a><br>Interface by Ana Carolina Rodrigues\
|
| 282 |
+
<a href="https://github.com/anasampa"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-github" viewBox="0 0 16 16">\
|
| 283 |
+
<path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27s1.36.09 2 .27c1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.01 8.01 0 0 0 16 8c0-4.42-3.58-8-8-8"/>\
|
| 284 |
+
</svg></i></a></p>',unsafe_allow_html=True)
|
not_used_Dockerfile
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
FROM python:3.11-slim
|
| 2 |
+
|
| 3 |
+
WORKDIR /app
|
| 4 |
+
|
| 5 |
+
RUN apt-get update && apt-get install -y \
|
| 6 |
+
build-essential \
|
| 7 |
+
curl \
|
| 8 |
+
software-properties-common \
|
| 9 |
+
git \
|
| 10 |
+
&& rm -rf /var/lib/apt/lists/*
|
| 11 |
+
|
| 12 |
+
COPY requirements.txt ./
|
| 13 |
+
COPY src/ ./src/
|
| 14 |
+
|
| 15 |
+
RUN pip3 install -r requirements.txt
|
| 16 |
+
|
| 17 |
+
EXPOSE 8501
|
| 18 |
+
|
| 19 |
+
HEALTHCHECK CMD curl --fail http://localhost:8501/_stcore/health
|
| 20 |
+
|
| 21 |
+
ENTRYPOINT ["streamlit", "run", "app.py", "--server.port=8501", "--server.address=0.0.0.0"]
|
requirements.txt
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
keras
|
| 2 |
+
torch
|
| 3 |
+
--extra-index-url=https://download.pytorch.org/whl/cu118
|
| 4 |
+
transformers
|
| 5 |
+
ufal.chu-liu-edmonds
|
| 6 |
+
streamlit
|
| 7 |
+
pandas
|
| 8 |
+
huggingface_hub
|
runtime.txt
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
python-3.11
|
src/annotation/setP11.sh
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Install Python3 and Libraries as a local user.
|
| 2 |
+
python_config() {
|
| 3 |
+
export PYTHON_VER="3.11.11"
|
| 4 |
+
export PYTHON_VER_SHORT="$(echo ${PYTHON_VER} | cut -d '.' -f1,2)"
|
| 5 |
+
export PYTHON_REQ="/evalatin2024-latinpipe/requirements.txt"
|
| 6 |
+
cd ~
|
| 7 |
+
rm -rf ~/python && mkdir -p ~/python
|
| 8 |
+
echo "" >> ~/.bashrc
|
| 9 |
+
echo "export PATH=~/python/bin:$PATH" >> ~/.bashrc
|
| 10 |
+
source ~/.bashrc
|
| 11 |
+
wget --quiet --no-check-certificate "https://www.python.org/ftp/python/${PYTHON_VER}/Python-${PYTHON_VER}.tgz"
|
| 12 |
+
tar -zxvf ~/Python-${PYTHON_VER}.tgz 1>/dev/null
|
| 13 |
+
cd ~/Python-${PYTHON_VER}/
|
| 14 |
+
echo "Python ${PYTHON_VER} - Installing in current logged-in user - $(whoami)"
|
| 15 |
+
echo "Python ${PYTHON_VER} - Installation in-progress. Please wait..."
|
| 16 |
+
./configure --enable-optimizations --prefix=$HOME/python > /dev/null 2>&1;
|
| 17 |
+
echo "Python ${PYTHON_VER} - ETA: upto 5mins. Please wait..."
|
| 18 |
+
make altinstall > /dev/null 2>&1;
|
| 19 |
+
ln -s ~/python/bin/python${PYTHON_VER_SHORT} ~/python/bin/python3
|
| 20 |
+
ln -s ~/python/bin/pip${PYTHON_VER_SHORT} ~/python/bin/pip3
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
# Install PIP3
|
| 24 |
+
wget --quiet --no-check-certificate https://bootstrap.pypa.io/get-pip.py -O - | python3 - --prefix=$HOME/python
|
| 25 |
+
source ~/.bashrc
|
| 26 |
+
~/python/bin/pip3 install --upgrade pip
|
| 27 |
+
~/python/bin/pip3 install --upgrade --no-cache-dir -r ${PYTHON_REQ} --use-pep517
|
| 28 |
+
cd ~ && rm -rf ~/Python-${PYTHON_VER}*
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
~/python/bin/python3 --version
|
| 32 |
+
~/python/bin/pip3 --version
|
| 33 |
+
echo "Python ${PYTHON_VER} - Setup Completed!"
|
| 34 |
+
}
|
| 35 |
+
|
| 36 |
+
# Function Call
|
| 37 |
+
python_config
|
src/arborator-draft/ArboratorDraft.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
new ArboratorDraft();
|
src/arborator-draft/FileSaver.min.js
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
(function(a,b){if("function"==typeof define&&define.amd)define([],b);else if("undefined"!=typeof exports)b();else{b(),a.FileSaver={exports:{}}.exports}})(this,function(){"use strict";function b(a,b){return"undefined"==typeof b?b={autoBom:!1}:"object"!=typeof b&&(console.warn("Deprecated: Expected third argument to be a object"),b={autoBom:!b}),b.autoBom&&/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(a.type)?new Blob(["\uFEFF",a],{type:a.type}):a}function c(a,b,c){var d=new XMLHttpRequest;d.open("GET",a),d.responseType="blob",d.onload=function(){g(d.response,b,c)},d.onerror=function(){console.error("could not download file")},d.send()}function d(a){var b=new XMLHttpRequest;b.open("HEAD",a,!1);try{b.send()}catch(a){}return 200<=b.status&&299>=b.status}function e(a){try{a.dispatchEvent(new MouseEvent("click"))}catch(c){var b=document.createEvent("MouseEvents");b.initMouseEvent("click",!0,!0,window,0,0,0,80,20,!1,!1,!1,!1,0,null),a.dispatchEvent(b)}}var f="object"==typeof window&&window.window===window?window:"object"==typeof self&&self.self===self?self:"object"==typeof global&&global.global===global?global:void 0,a=/Macintosh/.test(navigator.userAgent)&&/AppleWebKit/.test(navigator.userAgent)&&!/Safari/.test(navigator.userAgent),g=f.saveAs||("object"!=typeof window||window!==f?function(){}:"download"in HTMLAnchorElement.prototype&&!a?function(b,g,h){var i=f.URL||f.webkitURL,j=document.createElement("a");g=g||b.name||"download",j.download=g,j.rel="noopener","string"==typeof b?(j.href=b,j.origin===location.origin?e(j):d(j.href)?c(b,g,h):e(j,j.target="_blank")):(j.href=i.createObjectURL(b),setTimeout(function(){i.revokeObjectURL(j.href)},4E4),setTimeout(function(){e(j)},0))}:"msSaveOrOpenBlob"in navigator?function(f,g,h){if(g=g||f.name||"download","string"!=typeof f)navigator.msSaveOrOpenBlob(b(f,h),g);else if(d(f))c(f,g,h);else{var i=document.createElement("a");i.href=f,i.target="_blank",setTimeout(function(){e(i)})}}:function(b,d,e,g){if(g=g||open("","_blank"),g&&(g.document.title=g.document.body.innerText="downloading..."),"string"==typeof b)return c(b,d,e);var h="application/octet-stream"===b.type,i=/constructor/i.test(f.HTMLElement)||f.safari,j=/CriOS\/[\d]+/.test(navigator.userAgent);if((j||h&&i||a)&&"undefined"!=typeof FileReader){var k=new FileReader;k.onloadend=function(){var a=k.result;a=j?a:a.replace(/^data:[^;]*;/,"data:attachment/file;"),g?g.location.href=a:location=a,g=null},k.readAsDataURL(b)}else{var l=f.URL||f.webkitURL,m=l.createObjectURL(b);g?g.location=m:location.href=m,g=null,setTimeout(function(){l.revokeObjectURL(m)},4E4)}});f.saveAs=g.saveAs=g,"undefined"!=typeof module&&(module.exports=g)});
|
| 2 |
+
|
| 3 |
+
//# sourceMappingURL=FileSaver.min.js.map
|
src/arborator-draft/arborator-draft.css
ADDED
|
@@ -0,0 +1,250 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
.token {
|
| 2 |
+
font: 18px DejaVu Sans;
|
| 3 |
+
fill: black;
|
| 4 |
+
font-family:sans-serif;
|
| 5 |
+
--wordDistance:33;
|
| 6 |
+
text-align: center;
|
| 7 |
+
}
|
| 8 |
+
.FORM {
|
| 9 |
+
/* font: 18px DejaVu Sans; */
|
| 10 |
+
/* fill: black; */
|
| 11 |
+
/* font-family:sans-serif; */
|
| 12 |
+
--wordDistance:55;
|
| 13 |
+
fill:black;
|
| 14 |
+
text-align: center;
|
| 15 |
+
}
|
| 16 |
+
|
| 17 |
+
.LEMMA {
|
| 18 |
+
font: 15px DejaVu Sans;
|
| 19 |
+
fill: black;
|
| 20 |
+
font-family:sans-serif;
|
| 21 |
+
text-align: center;
|
| 22 |
+
font-style: italic;
|
| 23 |
+
--wordDistance:22;
|
| 24 |
+
}
|
| 25 |
+
|
| 26 |
+
.MISC-Gloss {
|
| 27 |
+
font: 15px DejaVu Sans;
|
| 28 |
+
fill: rgb(124, 96, 86);
|
| 29 |
+
font-family:sans-serif;
|
| 30 |
+
text-align: center;
|
| 31 |
+
font-style: italic;
|
| 32 |
+
--wordDistance:11;
|
| 33 |
+
}
|
| 34 |
+
.UPOS {
|
| 35 |
+
font: 11px DejaVu Sans;
|
| 36 |
+
fill: rgb(80, 29, 125);
|
| 37 |
+
text-align: center;
|
| 38 |
+
--wordDistance:22;
|
| 39 |
+
}
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
|
| 43 |
+
.DEPREL {
|
| 44 |
+
font: 12px Arial;
|
| 45 |
+
fill: #501d7d;
|
| 46 |
+
font-style: oblique;
|
| 47 |
+
font-family:sans-serif;
|
| 48 |
+
--funcCurveDist:3; /* distance between the function name and the curves highest point */
|
| 49 |
+
}
|
| 50 |
+
|
| 51 |
+
|
| 52 |
+
.lemma {
|
| 53 |
+
font: 15px DejaVu Sans;
|
| 54 |
+
fill: black;
|
| 55 |
+
font-family:sans-serif;
|
| 56 |
+
text-align: center;
|
| 57 |
+
font-style: italic;
|
| 58 |
+
}
|
| 59 |
+
|
| 60 |
+
|
| 61 |
+
.MISC-Gloss {
|
| 62 |
+
font: 15px DejaVu Sans;
|
| 63 |
+
fill: rgb(124, 96, 86);
|
| 64 |
+
font-family:sans-serif;
|
| 65 |
+
text-align: center;
|
| 66 |
+
font-style: italic;
|
| 67 |
+
--wordDistance:11;
|
| 68 |
+
}
|
| 69 |
+
|
| 70 |
+
.xdeprel {
|
| 71 |
+
font: 12px Arial;
|
| 72 |
+
font-style: oblique;
|
| 73 |
+
fill: #21ba45;
|
| 74 |
+
--funcCurveDist:3; /* distance between the function name and the curves highest point */
|
| 75 |
+
|
| 76 |
+
}
|
| 77 |
+
|
| 78 |
+
.xdep {
|
| 79 |
+
stroke: #21ba45;
|
| 80 |
+
fill: none;
|
| 81 |
+
--startOffset: 8;
|
| 82 |
+
--tokDepDist: 15; /* distance between tokens and depdendency relation */
|
| 83 |
+
--depMinHeight: 15; /* minimum height for dependency */
|
| 84 |
+
--wordDistanceFactor: -1; /* distant words get higher curves. this factor fixes how much higher */
|
| 85 |
+
}
|
| 86 |
+
|
| 87 |
+
.arrowhead {
|
| 88 |
+
fill: white;
|
| 89 |
+
stroke: black;
|
| 90 |
+
stroke-width: .8;
|
| 91 |
+
}
|
| 92 |
+
|
| 93 |
+
.arrowheadxdep {
|
| 94 |
+
fill: white;
|
| 95 |
+
stroke: #21ba45;
|
| 96 |
+
stroke-width: .8;
|
| 97 |
+
}
|
| 98 |
+
|
| 99 |
+
.curve {
|
| 100 |
+
stroke: black;
|
| 101 |
+
stroke-width: 1;
|
| 102 |
+
fill: none;
|
| 103 |
+
--startOffset: 8;
|
| 104 |
+
--tokDepDist: 15; /* distance between tokens and depdendency relation */
|
| 105 |
+
--depMinHeight: 15; /* minimum height for dependency */
|
| 106 |
+
--wordDistanceFactor: -1; /* distant words get higher curves. this factor fixes how much higher */
|
| 107 |
+
}
|
| 108 |
+
|
| 109 |
+
.conll {
|
| 110 |
+
display:none; /*toggles to inline*/
|
| 111 |
+
unicode-bidi: embed;
|
| 112 |
+
font-family: monospace;
|
| 113 |
+
white-space: pre;
|
| 114 |
+
margin-bottom: 0.6em;
|
| 115 |
+
border-bottom: 1px solid #aaa;
|
| 116 |
+
padding: 0.5em 0 0.17em 0;
|
| 117 |
+
tab-size: 12;
|
| 118 |
+
background-color: #fff ;
|
| 119 |
+
box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.26);
|
| 120 |
+
}
|
| 121 |
+
|
| 122 |
+
.sentencebox {
|
| 123 |
+
margin-bottom: 0.6em;
|
| 124 |
+
border-bottom: 1px solid lightgrey;
|
| 125 |
+
padding: 0.5em 0 0.17em 0;
|
| 126 |
+
margin-top: 1em;
|
| 127 |
+
}
|
| 128 |
+
|
| 129 |
+
/* Button */
|
| 130 |
+
.button {
|
| 131 |
+
display: inline-block;
|
| 132 |
+
position: relative;
|
| 133 |
+
width: 120px;
|
| 134 |
+
height: 32px;
|
| 135 |
+
line-height: 32px;
|
| 136 |
+
border-radius: 2px;
|
| 137 |
+
font-size: 0.9em;
|
| 138 |
+
background-color: #fff;
|
| 139 |
+
color: #646464;
|
| 140 |
+
cursor:pointer;
|
| 141 |
+
}
|
| 142 |
+
|
| 143 |
+
.button > paper-ripple {
|
| 144 |
+
border-radius: 0px;
|
| 145 |
+
overflow: hidden;
|
| 146 |
+
}
|
| 147 |
+
|
| 148 |
+
|
| 149 |
+
.button.raised {
|
| 150 |
+
transition: box-shadow 0.2s cubic-bezier(0.4, 0, 0.2, 1);
|
| 151 |
+
transition-delay: 0.2s;
|
| 152 |
+
box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.26);
|
| 153 |
+
}
|
| 154 |
+
|
| 155 |
+
.button.raised:active {
|
| 156 |
+
box-shadow: 0 8px 17px 0 rgba(0, 0, 0, 0.2);
|
| 157 |
+
transition-delay: 0s;
|
| 158 |
+
}
|
| 159 |
+
|
| 160 |
+
.center {
|
| 161 |
+
text-align: center;
|
| 162 |
+
}
|
| 163 |
+
|
| 164 |
+
|
| 165 |
+
.svgbox {
|
| 166 |
+
overflow-x: auto;
|
| 167 |
+
}
|
| 168 |
+
|
| 169 |
+
|
| 170 |
+
|
| 171 |
+
|
| 172 |
+
nav {
|
| 173 |
+
display: inline-block;
|
| 174 |
+
vertical-align: middle;
|
| 175 |
+
}
|
| 176 |
+
|
| 177 |
+
|
| 178 |
+
|
| 179 |
+
nav ul {
|
| 180 |
+
font-size: 0;
|
| 181 |
+
list-style: none;
|
| 182 |
+
margin: 0;
|
| 183 |
+
padding: 0;
|
| 184 |
+
/* text-align: center; */
|
| 185 |
+
width: 100%;
|
| 186 |
+
|
| 187 |
+
}
|
| 188 |
+
nav li {
|
| 189 |
+
display: inline-block;
|
| 190 |
+
margin: 0;
|
| 191 |
+
padding: 0;
|
| 192 |
+
position: relative;
|
| 193 |
+
/* min-width: 33%; */
|
| 194 |
+
|
| 195 |
+
}
|
| 196 |
+
nav a {
|
| 197 |
+
|
| 198 |
+
display: block;
|
| 199 |
+
font: normal 16px sans-serif;
|
| 200 |
+
padding-right: 9px;
|
| 201 |
+
text-decoration: none;
|
| 202 |
+
-webkit-transition: all .25s ease;
|
| 203 |
+
-moz-transition: all .25s ease;
|
| 204 |
+
-ms-transition: all .25s ease;
|
| 205 |
+
-o-transition: all .25s ease;
|
| 206 |
+
transition: all .25s ease;
|
| 207 |
+
|
| 208 |
+
}
|
| 209 |
+
|
| 210 |
+
nav li ul li:hover a {
|
| 211 |
+
background: #f5f5f5;
|
| 212 |
+
}
|
| 213 |
+
nav li ul {
|
| 214 |
+
|
| 215 |
+
background: #fff;
|
| 216 |
+
left: 0;
|
| 217 |
+
opacity: 0;
|
| 218 |
+
position: absolute;
|
| 219 |
+
top: 10px;
|
| 220 |
+
visibility: hidden;
|
| 221 |
+
z-index: 1;
|
| 222 |
+
-webkit-transition: all .25s ease;
|
| 223 |
+
-moz-transition: all .25s ease;
|
| 224 |
+
-ms-transition: all .25s ease;
|
| 225 |
+
-o-transition: all .25s ease;
|
| 226 |
+
transition: all .25s ease;
|
| 227 |
+
}
|
| 228 |
+
nav li:hover ul {
|
| 229 |
+
opacity: 1;
|
| 230 |
+
top: 23px;
|
| 231 |
+
visibility: visible;
|
| 232 |
+
}
|
| 233 |
+
nav li ul li {
|
| 234 |
+
width: 130px;
|
| 235 |
+
display: inline-block;
|
| 236 |
+
border-bottom: 1px solid lightgrey;
|
| 237 |
+
background: #fff;
|
| 238 |
+
cursor:pointer;
|
| 239 |
+
|
| 240 |
+
}
|
| 241 |
+
nav li ul a {
|
| 242 |
+
color: #000;
|
| 243 |
+
font: normal 16px/32px sans-serif
|
| 244 |
+
}
|
| 245 |
+
nav li ul a:hover {
|
| 246 |
+
color: #501d7d;
|
| 247 |
+
|
| 248 |
+
text-decoration: none;
|
| 249 |
+
}
|
| 250 |
+
|
src/arborator-draft/arborator-draft.js
ADDED
|
@@ -0,0 +1,691 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
(function () {
|
| 2 |
+
|
| 3 |
+
/*!
|
| 4 |
+
* arborator script for dependency drawing
|
| 5 |
+
* version 2.0
|
| 6 |
+
* http://arborator.ilpga.fr/
|
| 7 |
+
*
|
| 8 |
+
* Copyright 2010-2020, Kim Gerdes & Gaël Guibon
|
| 9 |
+
*
|
| 10 |
+
* This program is free software:
|
| 11 |
+
* Licensed under version 3 of the GNU Affero General Public License (the "License");
|
| 12 |
+
* you may not use this file except in compliance with the License.
|
| 13 |
+
* You may obtain a copy of the License at http://www.gnu.org/licenses/agpl-3.0.html
|
| 14 |
+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS,
|
| 15 |
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 16 |
+
* See the License for the specific language governing permissions and limitations under the License.
|
| 17 |
+
*
|
| 18 |
+
*/
|
| 19 |
+
|
| 20 |
+
// global variables:
|
| 21 |
+
fontSize = 0; // computed from css value for .token in arborator-draft.css
|
| 22 |
+
svgDefaultHeight = 350;//500;
|
| 23 |
+
el=10; // type of conll (10, 14, or 4), computed in conllNodesToTree
|
| 24 |
+
trees=[]; // list of tree objects
|
| 25 |
+
uextras=[]; // list of comments. each comment is a hashtable position(=line)->comment
|
| 26 |
+
conlltrees=[]; // list of conll strings
|
| 27 |
+
sentences=[]; // list of sentence strings
|
| 28 |
+
theshownfeatures=["FORM", "UPOS", "LEMMA", "MISC.Gloss"]; // recomputed in readConll
|
| 29 |
+
shownmetas=['text_en'];
|
| 30 |
+
showAllConllButton = false;
|
| 31 |
+
progressiveLoading = true; // false to make it load all trees at once (may overload the browser)
|
| 32 |
+
reverseMode = false; // set true for right to left conll
|
| 33 |
+
conlls = {
|
| 34 |
+
10: {"ID": 0, "FORM":1, "LEMMA": 2, "UPOS": 3, "XPOS":4, "FEATS":5, "HEAD":6, "DEPREL":7, "DEPS":8, "MISC":9},
|
| 35 |
+
14: {"ID": 0, "FORM":1, "LEMMA": 3, "UPOS": 5, "HEAD":9, "DEPREL":11},
|
| 36 |
+
4: {"FORM":0, "LEMMA": 0, "UPOS": 1, "HEAD":2, "DEPREL":3}
|
| 37 |
+
};
|
| 38 |
+
|
| 39 |
+
isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1; // needed for bezier bounding box bug
|
| 40 |
+
svgIdIndex = 0;
|
| 41 |
+
|
| 42 |
+
// debug:
|
| 43 |
+
log = console.log.bind(console);
|
| 44 |
+
|
| 45 |
+
arborator = `<svg
|
| 46 |
+
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
| 47 |
+
xmlns:cc="http://creativecommons.org/ns#"
|
| 48 |
+
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
| 49 |
+
xmlns:svg="http://www.w3.org/2000/svg"
|
| 50 |
+
xmlns="http://www.w3.org/2000/svg"
|
| 51 |
+
version="1.1"
|
| 52 |
+
viewBox="-4202 0 5704.1939 1840.839"
|
| 53 |
+
style="image-rendering:optimizeQuality;"
|
| 54 |
+
height="13"
|
| 55 |
+
width="27"
|
| 56 |
+
xml:space="preserve">
|
| 57 |
+
<path
|
| 58 |
+
style="fill:none;stroke:#4a2769;stroke-width:128.73750305;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;"
|
| 59 |
+
d="m -1890.5398,1002.7933 -1822.5445,615.288 c -261.3344,-190.4146 -424.5469,-433.2903 -424.5469,-661.59345 0,-685.88115 1244.2446,-1296.6446 2780.191,-1296.6446 1534.97478,0 2795.2653,610.76345 2795.2653,1296.6446 0,685.88105 -1252.26757,1244.49535 -2787.2424,1244.49535 -239.9613,0 -490.6091,-19.4301 -718.9123,-43.7176 L -751.94297,618.40481 -882.8496,663.4494" /><path
|
| 60 |
+
style="fill:none;stroke:#dd137b;stroke-width:128.73750305;stroke-miterlimit:4;"
|
| 61 |
+
d="M -864.53567,745.22843 C -964.68477,501.46149 -1354.4152,-183.90675 -1694.5756,-3.2652517 -2014.6556,165.68318 -2049.9732,423.17981 -1871.2632,1084.3717 c 67.0564,232.3776 161.3346,398.0135 238.7197,540.6756" /><path
|
| 62 |
+
style="fill:none;stroke:#4a2769;stroke-width:128.73750305;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;"
|
| 63 |
+
d="M -2068.3297,2157.2657 -751.94297,618.40481"
|
| 64 |
+
/>
|
| 65 |
+
</svg>`;
|
| 66 |
+
|
| 67 |
+
const defaultcss = `
|
| 68 |
+
.FORM { font: 18px DejaVu Sans; fill: black; font-family:sans-serif; text-align: center; }
|
| 69 |
+
.LEMMA { font: 15px DejaVu Sans; fill: black; font-family:sans-serif; text-align: center; font-style: italic; }
|
| 70 |
+
.UPOS { font: 11px DejaVu Sans; fill: rgb(80, 29, 125); text-align: center; }
|
| 71 |
+
.MISC-Gloss {font: 15px DejaVu Sans; fill: rgb(124, 96, 86); font-family:sans-serif; text-align: center; font-style: italic;}
|
| 72 |
+
.DEPREL { font: 12px Arial; fill: #1d2ec1; font-style: oblique; font-family:sans-serif; }
|
| 73 |
+
.arrowhead { fill: white; stroke: black; stroke-width:.8;}
|
| 74 |
+
.arrowheadxdep { fill: white;stroke: #21ba45;stroke-width:.8;}
|
| 75 |
+
.xdep { stroke: #21ba45; stroke-width: 1; fill: none;}
|
| 76 |
+
.curve { stroke: black; stroke-width: 1; fill: none;}
|
| 77 |
+
.xdeprel { font: 12px Arial; font-style: oblique; fill: #21ba45; }
|
| 78 |
+
.svgbox { overflow-x: auto; }`;
|
| 79 |
+
|
| 80 |
+
|
| 81 |
+
// public initialisation function
|
| 82 |
+
this.ArboratorDraft = function(shownfeatures=false, reverse = false, visuMode = 0) {
|
| 83 |
+
// main function called from html file
|
| 84 |
+
if (shownfeatures) {theshownfeatures = shownfeatures;}
|
| 85 |
+
if(reverse) reverseMode = true;
|
| 86 |
+
if(visuMode==0){
|
| 87 |
+
$( ".expander" ).click(function(){
|
| 88 |
+
$(this).next('conll').toggle();});
|
| 89 |
+
readConll();
|
| 90 |
+
}
|
| 91 |
+
else{
|
| 92 |
+
// log('[ArboratorDraft] visumode');
|
| 93 |
+
trees=[];
|
| 94 |
+
uextras=[];
|
| 95 |
+
conlltrees=[];
|
| 96 |
+
sentences=[];
|
| 97 |
+
$('conll').hide();
|
| 98 |
+
refresh( $('#conllarea').text() );
|
| 99 |
+
}
|
| 100 |
+
}
|
| 101 |
+
|
| 102 |
+
// public function
|
| 103 |
+
ArboratorDraft.prototype.emptyThenRefresh = function(content, reverse = false, toggle = false) {
|
| 104 |
+
if(reverse) reverseMode = true; // to set reverse or not
|
| 105 |
+
if(toggle) reverseMode = !reverseMode; // to toggle reverse
|
| 106 |
+
empty().done( refresh( content ) );
|
| 107 |
+
}
|
| 108 |
+
|
| 109 |
+
function refresh(content) {
|
| 110 |
+
$('#svgwell').html('');
|
| 111 |
+
$('#svgwell').append( $("<conll></conll>").attr('id', 'transformhere').text( content ) );
|
| 112 |
+
var conll = d3.selectAll('#transformhere')['_groups'][0][0];
|
| 113 |
+
drawConll(conll);
|
| 114 |
+
return;
|
| 115 |
+
}
|
| 116 |
+
|
| 117 |
+
function empty() {
|
| 118 |
+
var def = new jQuery.Deferred();
|
| 119 |
+
clearTimeout(readInsideConllTimeout);
|
| 120 |
+
treelines = [];
|
| 121 |
+
$('#svgwell').html('');
|
| 122 |
+
def.resolve();
|
| 123 |
+
return def.promise();
|
| 124 |
+
}
|
| 125 |
+
|
| 126 |
+
function progressiveReadConll() {
|
| 127 |
+
// draw each conll tags progressively (only conll tags)
|
| 128 |
+
var conllLoop = d3.selectAll('conll')['_groups'][0]; // need to go out d3js to load it progressively
|
| 129 |
+
var i = 0;
|
| 130 |
+
function waitBetweenElements(range) {
|
| 131 |
+
readConllTimeout = setTimeout(function () {
|
| 132 |
+
drawConll(conllLoop[i]);
|
| 133 |
+
i++;
|
| 134 |
+
if (i < range) {
|
| 135 |
+
waitBetweenElements(range);
|
| 136 |
+
}
|
| 137 |
+
}, 10)
|
| 138 |
+
}
|
| 139 |
+
waitBetweenElements(conllLoop.length);
|
| 140 |
+
}
|
| 141 |
+
|
| 142 |
+
function progressiveReadInsideConll(trees, pnode) {
|
| 143 |
+
// draw each tree INSIDE a conll progressively
|
| 144 |
+
var iWait = 0;
|
| 145 |
+
function waitBetweenElements(range) {
|
| 146 |
+
readInsideConllTimeout = setTimeout(function () {
|
| 147 |
+
pushAndDrawSVG(trees[iWait], pnode);
|
| 148 |
+
iWait++;
|
| 149 |
+
if (iWait < range) waitBetweenElements(range);
|
| 150 |
+
}, 10)
|
| 151 |
+
}
|
| 152 |
+
waitBetweenElements(trees.length);
|
| 153 |
+
}
|
| 154 |
+
|
| 155 |
+
function pushAndDrawSVG(element, pnode) {
|
| 156 |
+
conlltrees.push(element);
|
| 157 |
+
var data=conllNodesToTree(element);
|
| 158 |
+
trees.push(data.tree);
|
| 159 |
+
uextras.push(data.uextra)
|
| 160 |
+
sentences.push(data.sentence)
|
| 161 |
+
|
| 162 |
+
var toggle = true;
|
| 163 |
+
var divsvgbox = pnode.insert('div').attr("class", 'svgbox');
|
| 164 |
+
var divsentbox = divsvgbox.insert('div').attr("class", 'sentencebox')
|
| 165 |
+
divsentbox.insert('nav').html(`
|
| 166 |
+
<ul>
|
| 167 |
+
<li>
|
| 168 |
+
<a>`+arborator+`</a>
|
| 169 |
+
<ul>
|
| 170 |
+
<li id="showconll`+svgIdIndex+`"><a>🗏 Show CoNLL</a></li>
|
| 171 |
+
<li id="pnglink`+svgIdIndex+`"><a>🖼 Save PNG</a></li>
|
| 172 |
+
<li id="svglink`+svgIdIndex+`"><a>🖍️ Save SVG</a></li>
|
| 173 |
+
<li ><a href="https://github.com/Arborator/arborator-draft" target="_blank">🛈 Info Arborator</a></li>
|
| 174 |
+
</ul>
|
| 175 |
+
</li>
|
| 176 |
+
</ul>`);
|
| 177 |
+
$("#pnglink"+svgIdIndex).click(function(){savePng(this.id);});
|
| 178 |
+
$("#svglink"+svgIdIndex).click(function(){saveSvg(this.id);});
|
| 179 |
+
divsentbox.insert('span').html(data.sentence);
|
| 180 |
+
for (shom of shownmetas) {
|
| 181 |
+
if (shom in data.metas)
|
| 182 |
+
if (shom.startsWith("text")) divsentbox.insert('div').html("<i>‘"+data.metas[shom]+"’</i>")
|
| 183 |
+
else divsentbox.insert('div').html(data.metas[shom])
|
| 184 |
+
}
|
| 185 |
+
var thisconll = divsentbox.insert('conll').html(element).attr('class', 'conll');
|
| 186 |
+
$("#showconll"+svgIdIndex).click(function(){
|
| 187 |
+
toggle = !toggle;
|
| 188 |
+
thisconll.style("display", toggle ? "none" : "block");
|
| 189 |
+
$(this.childNodes[0]).html(toggle ? "🗏 Show CoNLL": "🗏 Hide CoNLL") //
|
| 190 |
+
});
|
| 191 |
+
thisconll.style("display", toggle ? "none" : "block");
|
| 192 |
+
draw(divsvgbox, data.tree);
|
| 193 |
+
svgIdIndex=svgIdIndex +1;
|
| 194 |
+
}
|
| 195 |
+
|
| 196 |
+
function readConll() {
|
| 197 |
+
// reads the conll representation of the whole treebank that is in the conll field
|
| 198 |
+
trees=[]; // list of tree objects
|
| 199 |
+
uextras=[]; // list of comments. each comment is a hashtable position(=line)->comment
|
| 200 |
+
conlltrees=[]; // list of conll strings, one string per tree
|
| 201 |
+
sentences=[]; // list of sentence strings, one string per tree
|
| 202 |
+
$('conll').hide(); // to hide the huge conll data
|
| 203 |
+
if(progressiveLoading) {
|
| 204 |
+
progressiveReadConll(); // progressive draw
|
| 205 |
+
}
|
| 206 |
+
else {
|
| 207 |
+
d3.selectAll('conll').each(function(d){ drawConll(this); }); // all at once
|
| 208 |
+
}
|
| 209 |
+
}
|
| 210 |
+
|
| 211 |
+
function drawConll(conllElement) { // for each <conll> section:
|
| 212 |
+
var pnode = d3.select(conllElement.parentNode);
|
| 213 |
+
if(showAllConllButton){
|
| 214 |
+
var conll = d3.select(conllElement).attr("class", 'conll');
|
| 215 |
+
conll.html(conll.html().trim())
|
| 216 |
+
var toggle = false;
|
| 217 |
+
var showHideConll = pnode.insert('div').html('<div class="center" fit>VIEW CONLL</div> <paper-ripple fit></paper-ripple>').attr("class", 'button raised');
|
| 218 |
+
var conllContent = conll.html().trim();
|
| 219 |
+
conll.remove(); // remove the old conll because its place wasn't good
|
| 220 |
+
conll = pnode.insert('conll').html(conllContent).attr('class', 'conll'); //re insert to bind the content
|
| 221 |
+
showHideConll.on("click", ()=>{
|
| 222 |
+
conll.style("display", toggle ? "none" : "block");
|
| 223 |
+
showHideConll.html(toggle ? '<div class="center" fit>VIEW CONLL</div> <paper-ripple fit></paper-ripple>': '<div class="center" fit>HIDE CONLL</div> <paper-ripple fit></paper-ripple>');
|
| 224 |
+
toggle = !toggle;
|
| 225 |
+
});
|
| 226 |
+
}
|
| 227 |
+
treelines = conllElement.textContent.trim().split(/\n\s*\n\s*\n*/);
|
| 228 |
+
if(progressiveLoading) {
|
| 229 |
+
progressiveReadInsideConll(treelines, pnode);
|
| 230 |
+
}
|
| 231 |
+
else {
|
| 232 |
+
for (let singleConll of treelines) { // for each conll tree at once, can block the browser
|
| 233 |
+
pushAndDrawSVG(singleConll, pnode);
|
| 234 |
+
}
|
| 235 |
+
}
|
| 236 |
+
}
|
| 237 |
+
|
| 238 |
+
function conllNodesToTree(treeline) {
|
| 239 |
+
var nodes = treeline.split('\n');
|
| 240 |
+
if(reverseMode) nodes.reverse();
|
| 241 |
+
var tree={};
|
| 242 |
+
var META={}; // sentence features before the actual conll
|
| 243 |
+
var addLines={}; // node position to additional line
|
| 244 |
+
var uextra={}; // todo: check this for reconstruction of conllu
|
| 245 |
+
var lastid=0;
|
| 246 |
+
var skipuntil=0;
|
| 247 |
+
var words=[]
|
| 248 |
+
nodes.forEach(function (nodeline, id)
|
| 249 |
+
{ // for each conll line:
|
| 250 |
+
nodeline=nodeline.trim().replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
|
| 251 |
+
if (nodeline.charAt(0) == "#") // META
|
| 252 |
+
{
|
| 253 |
+
var [a,v] = nodeline.substring(1).trim().split("=")
|
| 254 |
+
if (v!=null) var [a,v]=[a.trim(),v.trim()]
|
| 255 |
+
META[a]=v
|
| 256 |
+
return true;
|
| 257 |
+
}
|
| 258 |
+
var elements = nodeline.split('\t');
|
| 259 |
+
el=elements.length;
|
| 260 |
+
if(el > 1)
|
| 261 |
+
{
|
| 262 |
+
if (!(el in conlls) && el>10) el=10;
|
| 263 |
+
if (el > 4) id=elements[conlls[el]["ID"]];
|
| 264 |
+
else if (elements[conlls[el]['FORM']] != "_") id++;
|
| 265 |
+
var form=elements[conlls[el]['FORM']];
|
| 266 |
+
var tokids=id.split("-")
|
| 267 |
+
if (tokids.length == 1) { // simple token
|
| 268 |
+
tree[id]={};
|
| 269 |
+
tree[id]["ID"]=id;
|
| 270 |
+
tree[id]['FORM']=form;
|
| 271 |
+
tree[id]["LEMMA"]=elements[conlls[el]["LEMMA"]];
|
| 272 |
+
tree[id]['UPOS']=elements[conlls[el]['UPOS']];
|
| 273 |
+
tree[id]['HEAD']=parseInt(elements[conlls[el]['HEAD']]);
|
| 274 |
+
tree[id]['DEPREL']=elements[conlls[el]['DEPREL']];
|
| 275 |
+
tree[id]["FEATS"]={};
|
| 276 |
+
tree[id]["DEPS"]={};
|
| 277 |
+
tree[id]["MISC"]={};
|
| 278 |
+
if (id>skipuntil) words.push(form);
|
| 279 |
+
if (el==10) {
|
| 280 |
+
tree[id]["XPOS"] =elements[conlls[el]["XPOS"]];
|
| 281 |
+
tree[id]["FEATS"] = analyzeFeaturestring(elements[conlls[el]["FEATS"]], '=', '|');
|
| 282 |
+
tree[id]["DEPS"] = analyzeFeaturestring(elements[conlls[el]["DEPS"]], ':', '|');
|
| 283 |
+
tree[id]["MISC"] = analyzeFeaturestring(elements[conlls[el]["MISC"]], '=', '|');
|
| 284 |
+
}
|
| 285 |
+
}
|
| 286 |
+
else if (tokids.length == 2){ // n-m type multi-word encoding
|
| 287 |
+
skipuntil = parseInt(tokids[1])
|
| 288 |
+
words.push(elements[conlls[el]['FORM']]);
|
| 289 |
+
if (!(lastid in uextra)) uextra[lastid]=[];
|
| 290 |
+
uextra[lastid].push(nodeline);
|
| 291 |
+
}
|
| 292 |
+
else {
|
| 293 |
+
if (!(lastid in uextra)) uextra[lastid]=[];
|
| 294 |
+
uextra[lastid].push(nodeline);
|
| 295 |
+
}
|
| 296 |
+
}//end if el >1
|
| 297 |
+
else { // bizarre line
|
| 298 |
+
if (!(lastid in addLines)) addLines[lastid]=[];
|
| 299 |
+
addLines[lastid].push(nodeline);
|
| 300 |
+
if (tokids.length == 2){ // n-m type multi-word encoding
|
| 301 |
+
skipuntil = parseInt(tokids[1])
|
| 302 |
+
words.push(elements[conlls[el]['FORM']]);
|
| 303 |
+
}
|
| 304 |
+
tree[id]['HEAD']=parseInt(elements[conlls[el]['HEAD']]); // todo: think about this
|
| 305 |
+
tree[id]['DEPREL']=elements[conlls[el]['DEPREL']];
|
| 306 |
+
}
|
| 307 |
+
lastid=id;
|
| 308 |
+
});
|
| 309 |
+
// now always correcting the META.text feature. if this is not desired, uncomment this line:
|
| 310 |
+
// if {tree:tree, uextra:uextra, sentence:META['text']};
|
| 311 |
+
// got to contstruct the sentence
|
| 312 |
+
var sentence = [];
|
| 313 |
+
words.forEach(function (word, i) {
|
| 314 |
+
sentence.push(word);
|
| 315 |
+
if (!("SpaceAfter" in tree[i+1]["MISC"] && tree[i+1]["MISC"]["SpaceAfter"]=="No" )) sentence.push(" ");
|
| 316 |
+
// if(!reverseMode){
|
| 317 |
+
// if (i+1 in tree && !(("NoSpaceAfter" in tree[i+1]) && tree[i+1]["NoSpaceAfter"]==false)) sentence.push(" ");
|
| 318 |
+
// } else{ sentence.push(word); }
|
| 319 |
+
});
|
| 320 |
+
META['text'] = sentence.join('')
|
| 321 |
+
if ('shownfeatures' in META) {
|
| 322 |
+
theshownfeatures = META['shownfeatures'].split(/,\s*/);
|
| 323 |
+
console.log(theshownfeatures);
|
| 324 |
+
}
|
| 325 |
+
return {tree:tree, uextra:uextra, sentence:META['text'], metas:META};
|
| 326 |
+
}
|
| 327 |
+
|
| 328 |
+
function analyzeFeaturestring(featstr, eq, spl) {
|
| 329 |
+
o={}
|
| 330 |
+
if (featstr.indexOf(eq) > -1){
|
| 331 |
+
featstr.split(spl).forEach(function (f) // for each feature:
|
| 332 |
+
{
|
| 333 |
+
var fs=f.split(eq)
|
| 334 |
+
if (fs.length >=2) {// if it's not just _
|
| 335 |
+
o[fs[0]]=fs.slice(1).join(eq);
|
| 336 |
+
}
|
| 337 |
+
});
|
| 338 |
+
}
|
| 339 |
+
return o;
|
| 340 |
+
}
|
| 341 |
+
|
| 342 |
+
function getSVGPath(startPoint,endPoint,computedStyle,ymove) {
|
| 343 |
+
// startPoint and endPoint are objects for the corresponding nodes
|
| 344 |
+
var tokDepDist = parseInt(computedStyle.getPropertyValue('--tokDepDist'));
|
| 345 |
+
var depMinHeight = parseInt(computedStyle.getPropertyValue('--depMinHeight'));
|
| 346 |
+
var wordDistanceFactor = parseInt(computedStyle.getPropertyValue('--wordDistanceFactor'));
|
| 347 |
+
if(reverseMode) wordDistanceFactor = -Math.abs(wordDistanceFactor);
|
| 348 |
+
var startOffset = parseInt(computedStyle.getPropertyValue('--startOffset'));
|
| 349 |
+
if(reverseMode) startOffset = -Math.abs(startOffset);
|
| 350 |
+
var startOff=(startPoint['ID']-endPoint['ID']>0)?-startOffset:startOffset
|
| 351 |
+
var x1 = startPoint['x']+startPoint['w']/2+startOff;
|
| 352 |
+
var x2 = endPoint['x']+endPoint['w']/2;
|
| 353 |
+
var y1 = svgDefaultHeight-fontSize*2;
|
| 354 |
+
var y2 = svgDefaultHeight-fontSize*2;
|
| 355 |
+
var x1x2=Math.abs(x1-x2)/2;
|
| 356 |
+
var yy = Math.max(y1-x1x2-wordDistanceFactor*Math.abs(endPoint['ID']-startPoint['ID']),-tokDepDist);
|
| 357 |
+
var yy = Math.min(yy,y1)-depMinHeight;
|
| 358 |
+
var cstr="M"+x1+","+y1+" C"+x1+","+yy+" "+x2+","+yy+" "+x2+","+(y2-2+ymove); // -2 so that the arrow is really pointed
|
| 359 |
+
//(x0,y0) is start point; (x1,y1),(x2,y2) is control points; (x3,y3) is end point.
|
| 360 |
+
return {cstr:cstr, x0:x1,y0:y1, x1:x1,y1:yy, x2:x2,y2:yy,x3:x2,y3:(y2-2)};
|
| 361 |
+
}
|
| 362 |
+
|
| 363 |
+
|
| 364 |
+
function arrowhead(x,y) {
|
| 365 |
+
// gives path for arrowhead x,y startpoint (end of arrow)
|
| 366 |
+
var size = 5;
|
| 367 |
+
var startpoint = x+","+y; // to move the arrowhead lower: (y+size/3);
|
| 368 |
+
var lefttop = "0,0" +(-size/2)+","+(-size*1.5)+" "+(-size/2)+","+(-size*1.5);
|
| 369 |
+
var righttop = (size/2)+"," +(size/2)+" "+(size/2)+"," +(size/2)+ " "+(size)+",0";
|
| 370 |
+
var arrowPath = "M"+ startpoint+"c"+lefttop+ "c"+righttop+ "z";
|
| 371 |
+
return arrowPath;
|
| 372 |
+
}
|
| 373 |
+
|
| 374 |
+
|
| 375 |
+
function drawDep(tree, id, govid, label, group, smallestY, curvestyle, relstyle, arrowstyle, rootlabels, ymove) {
|
| 376 |
+
var x = tree[id]['x'] + tree[id]['w'] / 2;
|
| 377 |
+
var depLine = group.append("path")
|
| 378 |
+
.attr("class", curvestyle)
|
| 379 |
+
.attr("d", function (dd) {
|
| 380 |
+
if (govid == 0) // sentence root:
|
| 381 |
+
{
|
| 382 |
+
var y = svgDefaultHeight - fontSize * 2;
|
| 383 |
+
return "M" + x + "," + (y - 2 + ymove) + "L" + x + "," + 0;
|
| 384 |
+
}
|
| 385 |
+
else // normal link:
|
| 386 |
+
{
|
| 387 |
+
pathInfo = getSVGPath(tree[govid], tree[id], getComputedStyle(this), ymove);
|
| 388 |
+
return pathInfo.cstr;
|
| 389 |
+
}
|
| 390 |
+
});
|
| 391 |
+
group.append("path")
|
| 392 |
+
.attr("class", arrowstyle)
|
| 393 |
+
.attr("d", function (dd) {
|
| 394 |
+
return arrowhead(x, svgDefaultHeight - fontSize * 2 +ymove);
|
| 395 |
+
});
|
| 396 |
+
var depLineBbox = depLine.node().getBBox();
|
| 397 |
+
if (govid == 0) // root link:
|
| 398 |
+
{
|
| 399 |
+
rootlabels.push(
|
| 400 |
+
group.append('text')
|
| 401 |
+
.attr("class", relstyle)
|
| 402 |
+
.text(label)
|
| 403 |
+
.attr("x", x+2)
|
| 404 |
+
.attr("y", 0)
|
| 405 |
+
);
|
| 406 |
+
}
|
| 407 |
+
else // normal link:
|
| 408 |
+
{
|
| 409 |
+
group.append('text')
|
| 410 |
+
.attr("class", relstyle)
|
| 411 |
+
.text(label)
|
| 412 |
+
.attr("x", function (d) {
|
| 413 |
+
relFontSize = parseInt(getComputedStyle(this).fontSize, 10);
|
| 414 |
+
var w = this.getComputedTextLength(); //<-- length of this node
|
| 415 |
+
return depLineBbox.x + depLineBbox.width / 2 - w / 2;
|
| 416 |
+
})
|
| 417 |
+
.attr("y", function (d) {
|
| 418 |
+
funcCurveDist = parseInt(getComputedStyle(this).getPropertyValue('--funcCurveDist'));
|
| 419 |
+
if (isFirefox) {
|
| 420 |
+
// firefox needs: stackoverflow.com/questions/24809978/calculating-the-bounding-box-of-cubic-bezier-curve
|
| 421 |
+
const { x0, y0, x1, y1, x2, y2, x3, y3 } = pathInfo; // firefox
|
| 422 |
+
y = bezierMinMax(x0, y0, x1, y1, x2, y2, x3, y3).min.y - funcCurveDist ;
|
| 423 |
+
return y; // firefox
|
| 424 |
+
}
|
| 425 |
+
else {
|
| 426 |
+
// standard Chrome etc
|
| 427 |
+
y = depLineBbox.y - funcCurveDist;
|
| 428 |
+
return y;
|
| 429 |
+
}
|
| 430 |
+
});
|
| 431 |
+
// if not root, check how high we got:
|
| 432 |
+
var smallY = y - relFontSize;
|
| 433 |
+
smallestY = smallY < smallestY ? smallY : smallestY;
|
| 434 |
+
}
|
| 435 |
+
return 3//smallestY
|
| 436 |
+
}
|
| 437 |
+
|
| 438 |
+
|
| 439 |
+
function draw(div, tree) {
|
| 440 |
+
// draws json tree on svg in div
|
| 441 |
+
var runningWidth = 0;
|
| 442 |
+
var smallestY = svgDefaultHeight;
|
| 443 |
+
var treeArray = $.map(tree, function(value) {return [value];});
|
| 444 |
+
var svg = div.append("svg:svg")
|
| 445 |
+
.attr("width", 1000)
|
| 446 |
+
.attr("height", svgDefaultHeight);
|
| 447 |
+
var group = svg.append("g");
|
| 448 |
+
var rootlabels = [];
|
| 449 |
+
// write tokens:
|
| 450 |
+
if(reverseMode) treeArray.reverse();
|
| 451 |
+
var eachTexts = group.selectAll("text")
|
| 452 |
+
.data(treeArray)
|
| 453 |
+
.enter();
|
| 454 |
+
eachTexts.append('text') // FORM
|
| 455 |
+
.attr("class", "FORM")
|
| 456 |
+
.text(function(d){ return d["FORM"]; } )
|
| 457 |
+
.attr("ID",function(d) { return d["ID"]; } )
|
| 458 |
+
.attr("x", function(d) {
|
| 459 |
+
var w = this.getComputedTextLength();
|
| 460 |
+
wordDistance = parseInt(getComputedStyle(this).getPropertyValue('--wordDistance'));
|
| 461 |
+
var x = runningWidth; //<-- previous length to return
|
| 462 |
+
runningWidth += w + wordDistance; //<-- total
|
| 463 |
+
tree[d["ID"]]["x"]=x;
|
| 464 |
+
tree[d["ID"]]["w"]=w;
|
| 465 |
+
fontSize = parseInt(getComputedStyle(this).fontSize, 10);
|
| 466 |
+
return x;
|
| 467 |
+
})
|
| 468 |
+
.attr("y", svgDefaultHeight-fontSize);
|
| 469 |
+
svg.attr("width", runningWidth); // adapt svg width
|
| 470 |
+
// draw dependency links:
|
| 471 |
+
group.selectAll("text").each(function(d) { // for each token:
|
| 472 |
+
var id = d3.select(this).attr("ID");
|
| 473 |
+
var govid = tree[id]["HEAD"];
|
| 474 |
+
var label = tree[id]["DEPREL"];
|
| 475 |
+
smallestY = drawDep(tree, id, govid, label, group, smallestY, "curve", "DEPREL","arrowhead", rootlabels, 0); // standard governor relation
|
| 476 |
+
for (var headid in tree[id]["DEPS"]) { // for each governor of extended dependency
|
| 477 |
+
smallestY = drawDep(tree, id, headid, tree[id]["DEPS"][headid], group, smallestY, "xdep", "xdeprel", "arrowheadxdep", rootlabels, -fontSize/2);
|
| 478 |
+
}
|
| 479 |
+
});
|
| 480 |
+
var lastheight = 0;
|
| 481 |
+
var h=0;
|
| 482 |
+
|
| 483 |
+
for (var fea of theshownfeatures) {
|
| 484 |
+
if (fea=="FORM") continue;
|
| 485 |
+
somet=false;
|
| 486 |
+
eachTexts.append('text')
|
| 487 |
+
.attr("class", fea.replace('.', '-'))
|
| 488 |
+
.text(function(d) {var t=fea.split('.').reduce((value,el) => value[el], d); if(!somet && t) somet=true; return t; } )
|
| 489 |
+
.attr("ID",function(d) {return d["ID"];})
|
| 490 |
+
.attr("x", function(d) {
|
| 491 |
+
// var lemmaLength = this.getComputedTextLength();
|
| 492 |
+
// var w = tree[d["ID"]]["w"];
|
| 493 |
+
wordDistance = parseInt(getComputedStyle(this).getPropertyValue('--wordDistance'));
|
| 494 |
+
h = parseInt(getComputedStyle(this).fontSize, 20);
|
| 495 |
+
return tree[d["ID"]]["x"]; //<-- previous length to return
|
| 496 |
+
})
|
| 497 |
+
.attr("y", svgDefaultHeight-fontSize+lastheight+h)
|
| 498 |
+
.append('title').text(function(d) {return fea.split('.').slice(-1)[0]+": "+fea.split('.').reduce((value,el) => value[el], d); });
|
| 499 |
+
if (somet) lastheight+=h; // found at least once the feature
|
| 500 |
+
}
|
| 501 |
+
// final adjustments:
|
| 502 |
+
for (rl of rootlabels) rl.attr("y",smallestY+fontSize)
|
| 503 |
+
group.attr("transform", "translate(" + 0 + "," + (-smallestY) + ")");
|
| 504 |
+
svg.attr("height", svgDefaultHeight-smallestY+lastheight+fontSize); // adapt svg height
|
| 505 |
+
svg.attr("id", "svg"+svgIdIndex);
|
| 506 |
+
svg.attr("version", '1.1'); // to prepare ddl of svg
|
| 507 |
+
svg.attr("xmlns", "http://www.w3.org/2000/svg"); // to prepare ddl of svg
|
| 508 |
+
}
|
| 509 |
+
|
| 510 |
+
|
| 511 |
+
function bezierMinMax(x0, y0, x1, y1, x2, y2, x3, y3) {
|
| 512 |
+
//(x0,y0) is start point; (x1,y1),(x2,y2) is control points; (x3,y3) is end point.
|
| 513 |
+
var tvalues = [], xvalues = [], yvalues = [], a, b, c, t, t1, t2, b2ac, sqrtb2ac;
|
| 514 |
+
for (var i = 0; i < 2; ++i) {
|
| 515 |
+
if (i == 0) {
|
| 516 |
+
b = 6 * x0 - 12 * x1 + 6 * x2;
|
| 517 |
+
a = -3 * x0 + 9 * x1 - 9 * x2 + 3 * x3;
|
| 518 |
+
c = 3 * x1 - 3 * x0;
|
| 519 |
+
}
|
| 520 |
+
else {
|
| 521 |
+
b = 6 * y0 - 12 * y1 + 6 * y2;
|
| 522 |
+
a = -3 * y0 + 9 * y1 - 9 * y2 + 3 * y3;
|
| 523 |
+
c = 3 * y1 - 3 * y0;
|
| 524 |
+
}
|
| 525 |
+
if (Math.abs(a) < 1e-12) {
|
| 526 |
+
if (Math.abs(b) < 1e-12) {
|
| 527 |
+
continue;
|
| 528 |
+
}
|
| 529 |
+
t = -c / b;
|
| 530 |
+
if (0 < t && t < 1) {
|
| 531 |
+
tvalues.push(t);
|
| 532 |
+
}
|
| 533 |
+
continue;
|
| 534 |
+
}
|
| 535 |
+
b2ac = b * b - 4 * c * a;
|
| 536 |
+
if (b2ac < 0) {
|
| 537 |
+
continue;
|
| 538 |
+
}
|
| 539 |
+
sqrtb2ac = Math.sqrt(b2ac);
|
| 540 |
+
t1 = (-b + sqrtb2ac) / (2 * a);
|
| 541 |
+
if (0 < t1 && t1 < 1) {
|
| 542 |
+
tvalues.push(t1);
|
| 543 |
+
}
|
| 544 |
+
t2 = (-b - sqrtb2ac) / (2 * a);
|
| 545 |
+
if (0 < t2 && t2 < 1) {
|
| 546 |
+
tvalues.push(t2);
|
| 547 |
+
}
|
| 548 |
+
}
|
| 549 |
+
var j = tvalues.length, mt;
|
| 550 |
+
while (j--) {
|
| 551 |
+
t = tvalues[j];
|
| 552 |
+
mt = 1 - t;
|
| 553 |
+
xvalues[j] = (mt * mt * mt * x0) + (3 * mt * mt * t * x1) + (3 * mt * t * t * x2) + (t * t * t * x3);
|
| 554 |
+
yvalues[j] = (mt * mt * mt * y0) + (3 * mt * mt * t * y1) + (3 * mt * t * t * y2) + (t * t * t * y3);
|
| 555 |
+
}
|
| 556 |
+
xvalues.push(x0,x3);
|
| 557 |
+
yvalues.push(y0,y3);
|
| 558 |
+
return {
|
| 559 |
+
min: {x: Math.min.apply(0, xvalues), y: Math.min.apply(0, yvalues)},
|
| 560 |
+
max: {x: Math.max.apply(0, xvalues), y: Math.max.apply(0, yvalues)}
|
| 561 |
+
};
|
| 562 |
+
}
|
| 563 |
+
|
| 564 |
+
function svg2Data(svg) {
|
| 565 |
+
var tempCSS = document.createElement("style");
|
| 566 |
+
tempCSS.innerHTML = defaultcss;
|
| 567 |
+
svg.insertBefore(tempCSS, svg.firstChild);
|
| 568 |
+
// svg.appendChild(tempCSS);
|
| 569 |
+
return {svg:svg, tempCSS:tempCSS};
|
| 570 |
+
}
|
| 571 |
+
|
| 572 |
+
function png2Data(svg) {
|
| 573 |
+
var canvas = document.createElement('canvas');
|
| 574 |
+
canvas.height = svg.height.baseVal.value*5;
|
| 575 |
+
canvas.width = svg.width.baseVal.value*5;
|
| 576 |
+
var tempCSS = document.createElement("style");
|
| 577 |
+
tempCSS.innerHTML = defaultcss;
|
| 578 |
+
svg.insertBefore(tempCSS, svg.firstChild); // === the missing prepend option
|
| 579 |
+
var data = (new XMLSerializer()).serializeToString(svg);
|
| 580 |
+
canvg(canvas, data, {'scaleWidth':canvas.width,'canvas.height':canvas.height,'ignoreDimensions':true});
|
| 581 |
+
return canvas.toDataURL().replace('data:image/png;base64,','');
|
| 582 |
+
}
|
| 583 |
+
|
| 584 |
+
function savePng(btnId) {
|
| 585 |
+
var id = btnId.replace("pnglink","");
|
| 586 |
+
var canvas = document.createElement('canvas');
|
| 587 |
+
var svg = document.getElementById("svg"+id);
|
| 588 |
+
var sdat = svg2Data(svg);
|
| 589 |
+
canvas.height = svg.height.baseVal.value*5;
|
| 590 |
+
canvas.width = svg.width.baseVal.value*5;
|
| 591 |
+
var ctx = canvas.getContext('2d');
|
| 592 |
+
var data = (new XMLSerializer()).serializeToString(svg);
|
| 593 |
+
var DOMURL = window.URL || window.webkitURL || window;
|
| 594 |
+
var img = new Image();
|
| 595 |
+
var svgBlob = new Blob([data], {type: 'image/svg+xml;charset=utf-8'});
|
| 596 |
+
var url = DOMURL.createObjectURL(svgBlob);
|
| 597 |
+
|
| 598 |
+
img.onload = function () {
|
| 599 |
+
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);//, 0, 0, ctx.width, ctx.height);
|
| 600 |
+
DOMURL.revokeObjectURL(url);
|
| 601 |
+
var imgURI = canvas
|
| 602 |
+
.toDataURL('image/png')
|
| 603 |
+
.replace('image/png', 'image/octet-stream');
|
| 604 |
+
var evt = new MouseEvent('click', {
|
| 605 |
+
view: window,
|
| 606 |
+
bubbles: false,
|
| 607 |
+
cancelable: true
|
| 608 |
+
});
|
| 609 |
+
var a = document.createElement('a');
|
| 610 |
+
a.setAttribute('download', sentences[id].match(/[a-zA-Z\u00c0-\u024f\u1e00-\u1eff]+/g).join(' ').split(" ").slice(0,5).join('_').slice(0,50)+'.png');
|
| 611 |
+
a.setAttribute('href', imgURI );
|
| 612 |
+
a.setAttribute('target', '_blank');
|
| 613 |
+
a.dispatchEvent(evt);
|
| 614 |
+
};
|
| 615 |
+
img.src = url;
|
| 616 |
+
|
| 617 |
+
svg.removeChild(sdat.tempCSS);
|
| 618 |
+
}
|
| 619 |
+
|
| 620 |
+
function saveSvg(btnId) {
|
| 621 |
+
var id = btnId.replace("svglink","");
|
| 622 |
+
var svg = document.getElementById("svg"+id);
|
| 623 |
+
sdat = svg2Data(svg);
|
| 624 |
+
var svgData = svg.outerHTML;
|
| 625 |
+
var svgBlob = new Blob([svgData], {type:"image/svg+xml;charset=utf-8"});
|
| 626 |
+
var svgUrl = URL.createObjectURL(svgBlob);
|
| 627 |
+
var downloadLink = document.createElement("a");
|
| 628 |
+
downloadLink.href = svgUrl;
|
| 629 |
+
downloadLink.download = sentences[id].match(/[a-zA-Z\u00c0-\u024f\u1e00-\u1eff]+/g).join(' ').split(" ").slice(0,5).join('_').slice(0,50)+".svg";
|
| 630 |
+
document.body.appendChild(downloadLink);
|
| 631 |
+
downloadLink.click();
|
| 632 |
+
document.body.removeChild(downloadLink);
|
| 633 |
+
svg.removeChild(sdat.tempCSS);
|
| 634 |
+
}
|
| 635 |
+
|
| 636 |
+
function exportPngZip() {
|
| 637 |
+
var filename = document.URL? document.URL.substring(document.URL.lastIndexOf('/')+1, document.URL.lastIndexOf('.')):'trees'
|
| 638 |
+
var zip = new JSZip();
|
| 639 |
+
var folder = zip.folder(filename+".PNGfiles");
|
| 640 |
+
var svgList = $('svg');
|
| 641 |
+
$.each( svgList, function( index, svg ){
|
| 642 |
+
if (svg.id) {
|
| 643 |
+
var pngData = png2Data(svg);
|
| 644 |
+
var sent = sentences[svg.id.replace('svg','')].match(/[a-zA-Z\u00c0-\u024f\u1e00-\u1eff]+/g).join(' ').split(" ").slice(0,5).join('_').slice(0,50)
|
| 645 |
+
folder.file('tree'+svg.id.replace('svg','')+'.'+sent+'.png', pngData, {base64: true});
|
| 646 |
+
}
|
| 647 |
+
});
|
| 648 |
+
zip.generateAsync({type:"blob"})
|
| 649 |
+
.then(function(content) {
|
| 650 |
+
saveAs(content, filename + ".png.export.zip");
|
| 651 |
+
|
| 652 |
+
});
|
| 653 |
+
}
|
| 654 |
+
|
| 655 |
+
function exportSvgZip() {
|
| 656 |
+
var zip = new JSZip();
|
| 657 |
+
var folder = zip.folder("svgfiles");
|
| 658 |
+
var svgList = $('svg');
|
| 659 |
+
$.each( svgList, function( index, svg ){
|
| 660 |
+
if (svg.id) {
|
| 661 |
+
var svgData = svg2Data(svg);
|
| 662 |
+
var sent = sentences[svg.id.replace('svg','')].match(/[a-zA-Z\u00c0-\u024f\u1e00-\u1eff]+/g).join(' ').split(" ").slice(0,5).join('_').slice(0,50)
|
| 663 |
+
folder.file('tree'+svg.id.replace('svg','')+'.'+sent+'.svg', svgData.svg.outerHTML);
|
| 664 |
+
}
|
| 665 |
+
});
|
| 666 |
+
// TODO:
|
| 667 |
+
// Add an top-level, arbitrary text file with contents
|
| 668 |
+
// zip.file("Hello.txt", "Hello World\n");
|
| 669 |
+
// Generate a directory within the Zip file structure
|
| 670 |
+
// var img = zip.folder("images");
|
| 671 |
+
// Add a file to the directory, in this case an image with data URI as contents
|
| 672 |
+
// img.file("smile.gif", imgData, {base64: true});
|
| 673 |
+
zip.generateAsync({type:"blob"})
|
| 674 |
+
.then(function(content) {
|
| 675 |
+
|
| 676 |
+
saveAs(content, (document.URL? document.URL.substring(document.URL.lastIndexOf('/')+1, document.URL.lastIndexOf('.')):'trees') + ".svg.export.zip");
|
| 677 |
+
});
|
| 678 |
+
}
|
| 679 |
+
|
| 680 |
+
$("#btnSvgZip").on("click", function (){
|
| 681 |
+
exportSvgZip();
|
| 682 |
+
});
|
| 683 |
+
|
| 684 |
+
$("#btnPngZip").on("click", function (){
|
| 685 |
+
exportPngZip();
|
| 686 |
+
});
|
| 687 |
+
|
| 688 |
+
|
| 689 |
+
}());
|
| 690 |
+
|
| 691 |
+
|
src/arborator-draft/arborator-draft2.css
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
.token {
|
| 2 |
+
font: 18px DejaVu Sans;
|
| 3 |
+
fill: black;
|
| 4 |
+
font-family:sans-serif;
|
| 5 |
+
--wordDistance:33;
|
| 6 |
+
text-align: center;
|
| 7 |
+
}
|
| 8 |
+
|
| 9 |
+
.lemma {
|
| 10 |
+
font: 15px DejaVu Sans;
|
| 11 |
+
fill: black;
|
| 12 |
+
font-family:sans-serif;
|
| 13 |
+
text-align: center;
|
| 14 |
+
font-style: italic;
|
| 15 |
+
}
|
| 16 |
+
|
| 17 |
+
.postag {
|
| 18 |
+
font: 11px DejaVu Sans;
|
| 19 |
+
fill: #E03737;
|
| 20 |
+
/* font-family:sans-serif; */
|
| 21 |
+
text-align: center;
|
| 22 |
+
}
|
| 23 |
+
|
| 24 |
+
.deprel {
|
| 25 |
+
font: 12px Arial;
|
| 26 |
+
fill: #1d2ec1;
|
| 27 |
+
font-style: oblique;
|
| 28 |
+
font-family:sans-serif;
|
| 29 |
+
--funcCurveDist:3; /* distance between the function name and the curves highest point */
|
| 30 |
+
}
|
| 31 |
+
|
| 32 |
+
.arrowhead {
|
| 33 |
+
fill: white;
|
| 34 |
+
stroke: black;
|
| 35 |
+
stroke-width: .8;
|
| 36 |
+
}
|
| 37 |
+
|
| 38 |
+
.curve {
|
| 39 |
+
stroke: black;
|
| 40 |
+
stroke-width: 1;
|
| 41 |
+
fill: none;
|
| 42 |
+
--startOffset: 8;
|
| 43 |
+
--tokDepDist: 15; /* distance between tokens and depdendency relation */
|
| 44 |
+
--depMinHeight: 15; /* minimum height for dependency */
|
| 45 |
+
--wordDistanceFactor: -1; /* distant words get higher curves. this factor fixes how much higher */
|
| 46 |
+
}
|
| 47 |
+
|
| 48 |
+
.conll {
|
| 49 |
+
display:none; /*toggles to inline*/
|
| 50 |
+
unicode-bidi: embed;
|
| 51 |
+
font-family: monospace;
|
| 52 |
+
white-space: pre;
|
| 53 |
+
margin-bottom: 0.6em;
|
| 54 |
+
border-bottom: 1px solid #aaa;
|
| 55 |
+
padding: 0.5em 0 0.17em 0;
|
| 56 |
+
tab-size: 12;
|
| 57 |
+
background-color: #fff ;
|
| 58 |
+
box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.26);
|
| 59 |
+
}
|
| 60 |
+
|
| 61 |
+
.sentencebox {
|
| 62 |
+
margin-bottom: 0.6em;
|
| 63 |
+
border-bottom: 1px solid #aaa;
|
| 64 |
+
padding: 0.5em 0 0.17em 0;
|
| 65 |
+
margin-top: 1em;
|
| 66 |
+
}
|
| 67 |
+
|
| 68 |
+
/* Button */
|
| 69 |
+
.button {
|
| 70 |
+
display: inline-block;
|
| 71 |
+
position: relative;
|
| 72 |
+
width: 120px;
|
| 73 |
+
height: 32px;
|
| 74 |
+
line-height: 32px;
|
| 75 |
+
border-radius: 2px;
|
| 76 |
+
font-size: 0.9em;
|
| 77 |
+
background-color: #fff;
|
| 78 |
+
color: #646464;
|
| 79 |
+
cursor:pointer;
|
| 80 |
+
}
|
| 81 |
+
|
| 82 |
+
.button > paper-ripple {
|
| 83 |
+
border-radius: 2px;
|
| 84 |
+
overflow: hidden;
|
| 85 |
+
}
|
| 86 |
+
|
| 87 |
+
|
| 88 |
+
.button.raised {
|
| 89 |
+
transition: box-shadow 0.2s cubic-bezier(0.4, 0, 0.2, 1);
|
| 90 |
+
transition-delay: 0.2s;
|
| 91 |
+
box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.26);
|
| 92 |
+
}
|
| 93 |
+
|
| 94 |
+
.button.raised:active {
|
| 95 |
+
box-shadow: 0 8px 17px 0 rgba(0, 0, 0, 0.2);
|
| 96 |
+
transition-delay: 0s;
|
| 97 |
+
}
|
| 98 |
+
|
| 99 |
+
.center {
|
| 100 |
+
text-align: center;
|
| 101 |
+
}
|
| 102 |
+
|
| 103 |
+
/* logo animation transitions */
|
| 104 |
+
.arboratorlogo {
|
| 105 |
+
transition: all 0.4s ease-in-out;
|
| 106 |
+
-webkit-transition: all 0.4s ease-in-out;
|
| 107 |
+
}
|
| 108 |
+
|
| 109 |
+
.arboratorlogo:hover {
|
| 110 |
+
transform: scale(1.1);
|
| 111 |
+
transition: all 0.2s ease-in-out;
|
| 112 |
+
-webkit-transition: all 0.2s ease-in-out;
|
| 113 |
+
opacity: .9;
|
| 114 |
+
}
|
| 115 |
+
|
| 116 |
+
.svgbox {
|
| 117 |
+
overflow-x: auto;
|
| 118 |
+
}
|
src/arborator-draft/arborator-draft2.js
ADDED
|
@@ -0,0 +1,720 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
(function () {
|
| 2 |
+
|
| 3 |
+
/*!
|
| 4 |
+
* arborator script for dependency drawing
|
| 5 |
+
* version 1.0
|
| 6 |
+
* http://arborator.ilpga.fr/
|
| 7 |
+
*
|
| 8 |
+
* Copyright 2010-2017, Kim Gerdes & Gaël Guibon
|
| 9 |
+
*
|
| 10 |
+
* This program is free software:
|
| 11 |
+
* Licensed under version 3 of the GNU Affero General Public License (the "License");
|
| 12 |
+
* you may not use this file except in compliance with the License.
|
| 13 |
+
* You may obtain a copy of the License at http://www.gnu.org/licenses/agpl-3.0.html
|
| 14 |
+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS,
|
| 15 |
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 16 |
+
* See the License for the specific language governing permissions and limitations under the License.
|
| 17 |
+
*
|
| 18 |
+
*/
|
| 19 |
+
|
| 20 |
+
var drag = d3.drag();
|
| 21 |
+
|
| 22 |
+
// global variables:
|
| 23 |
+
fontSize = 0; // computed from css value for .token in arborator-draft.css
|
| 24 |
+
lemmaHeight = 0;
|
| 25 |
+
posHeight = 0;
|
| 26 |
+
svgDefaultHeight = 500;
|
| 27 |
+
el=10; // type of conll (10, 14, or 4), computed in conllNodesToTree
|
| 28 |
+
trees=[]; // list of tree objects
|
| 29 |
+
uextras=[]; // list of comments. each comment is a hashtable position(=line)->comment TODO: add this to the display
|
| 30 |
+
conlltrees=[]; // list of conll strings
|
| 31 |
+
defaultCat="_"
|
| 32 |
+
shownfeatures=["t", "cat", "lemma","gloss"]; // recomputed in readConll
|
| 33 |
+
progressiveLoading = true; // false to make it load all trees at once (may overload the browser)
|
| 34 |
+
pngBtn = true;
|
| 35 |
+
svgBtn = true;
|
| 36 |
+
reverseMode = false; // set true for right to left conll
|
| 37 |
+
conlls = {
|
| 38 |
+
10: {"id": 0, "t":1, "lemma": 2, "cat": 3, "xpos":4, "morph":5, "gov":6, "func":7, "xgov":8, "gloss":9},
|
| 39 |
+
14: {"id": 0, "t":1, "lemma": 3, "cat": 5, "gov":9, "func":11},
|
| 40 |
+
4: {"t":0, "lemma": 0, "cat": 1, "gov":2, "func":3}
|
| 41 |
+
}
|
| 42 |
+
isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1; // needed for bezier bounding box bug
|
| 43 |
+
|
| 44 |
+
// debug:
|
| 45 |
+
log = console.log.bind(console);
|
| 46 |
+
|
| 47 |
+
// TODO: add lemmas and pos!!!
|
| 48 |
+
lemmaColor = '#006400';
|
| 49 |
+
posColor = '#9e04de';
|
| 50 |
+
|
| 51 |
+
// base 64 logo of arborator for the link image
|
| 52 |
+
base64Logo = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADQAAAAXCAYAAABEQGxzAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAABtQAAAbUBnmWvHAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAANXSURBVFiFtZhLbA1RGMd/59x7e5XeVrXU45aF9ztCLEQ3gojMwkZiJ7GYRDALhAUJa/FIZjk7EYKWCIMQG0qIx4JIQyREqxWP1uNyH729MxYzreu29zF3xj85mznf+X///8x3Zr4zwrZtqoWqaDXALKClggHwqYLx3jD1wWo1Ca+GVEWbAmwGFGAjECsWK22oyQkyYRsPWRLAbcAEbhim/tmLvooMqYq2HMeAAqwGZLk18USINb1RGjKSn1GLmpzgzOLfXrQBWMBjHHOmYerPyy0oakhVtGbgALANaPWioiEj2fGijmguT5mweThjkGdTsyTDlhe6fPQA54Fjhql/HStglCFV0WLAPmAvJcqpGOKJEOvej2P6r9CouZy0uT47TVdT1ittIRLASeCEYeqJ/Il/SkdVtJVAF3CEKswA1A0Kpv0ebQYgZAnaeqIs7A9XQ52PGI7GLlfzCEYMqYq2FegE4n4ytSRDiBLbsjEtaUyX3YKVIg50utoB15CqaBuBC0Ct3wxNqbGfTj7mDUSY9aN8XIWoBS64Hgj1PR1oBm5RZYkVYlDaLO6PlIyZkJV8q7Vf9dTnJAHcREAA66+du3laAvuBaQGQArDsS6TsN0cA44ZEDJgUVF4cD/sl0BYgKVfmphioLf1a7qvLca81PSPIvC7aJLAsSMZJaWk1pmVRR9+jFh3zkwwF9l74B0sk8C4AIgu4C+y2RHamgINjBaXDNu0LkiQj1fePZfAyDFwFllax2AIeABeBS4apfxyeeNd8uLVQck7A5Xkp+suUo090hoFTwE4q26A2jol2oMMw9b4icWeB9cCi4Qs3Z6forh/yJ7c0PgLHhW3bwx3CHWDiGIE28BDnSXQYpt5blloI8bbp0BNgJcD9eIb78Uxgyoto3GSY+u2RXk5VtFU4phrcgEf8NfHBa4a3kw8dwRZHXzZnMeekgpM+Gilgu2Hq7VDQnKqKthpYC7Qbpt7jJ8vryQdj3Q2i9/L8ZCwn/DCVxAdgi2Hqz4YveD7gVYpdm/dsBXkxK/8Lf9Fu+78YUhVtBfAECKxhc+H9POQXqqK14HzbgujRgjuxVgNV0SI4dT3FB42vfwq+T1oF2AC8ABqBeneMd4eFI/Yb8AXoA7qBNwT41+cPAlA7a3SX2xoAAAAASUVORK5CYII=';
|
| 53 |
+
|
| 54 |
+
svgIdIndex = 0;
|
| 55 |
+
|
| 56 |
+
// public initialisation function
|
| 57 |
+
this.ArboratorDraft = function(visuMode = 0, reverse = false) {
|
| 58 |
+
// main function called from html file
|
| 59 |
+
if(reverse) reverseMode = true;
|
| 60 |
+
if(visuMode==0){
|
| 61 |
+
$( ".expander" ).click(function(){
|
| 62 |
+
log(99,$(this).next('conll'));
|
| 63 |
+
$(this).next('conll').toggle();});
|
| 64 |
+
readConll();
|
| 65 |
+
}else{
|
| 66 |
+
console.log('[ArboratorDraft] visumode');
|
| 67 |
+
trees=[];
|
| 68 |
+
uextras=[];
|
| 69 |
+
conlltrees=[];
|
| 70 |
+
$('conll').hide();
|
| 71 |
+
refresh( $('#conllarea').text() );
|
| 72 |
+
}
|
| 73 |
+
}
|
| 74 |
+
|
| 75 |
+
// public function
|
| 76 |
+
ArboratorDraft.prototype.emptyThenRefresh = function(content, reverse = false, toggle = false) {
|
| 77 |
+
if(reverse) reverseMode = true; // to set reverse or not
|
| 78 |
+
if(toggle) reverseMode = !reverseMode; // to toggle reverse
|
| 79 |
+
empty().done( refresh( content ) );
|
| 80 |
+
}
|
| 81 |
+
|
| 82 |
+
|
| 83 |
+
function refresh(content) {
|
| 84 |
+
$('#svgwell').html('');
|
| 85 |
+
$('#svgwell').append( $("<conll></conll>").attr('id', 'transformhere').text( content ) );
|
| 86 |
+
var conll = d3.selectAll('#transformhere')['_groups'][0][0];
|
| 87 |
+
drawConll(conll);
|
| 88 |
+
return;
|
| 89 |
+
}
|
| 90 |
+
|
| 91 |
+
function sleep(milliseconds) {
|
| 92 |
+
var start = new Date().getTime();
|
| 93 |
+
for (var i = 0; i < 1e7; i++) {
|
| 94 |
+
if ((new Date().getTime() - start) > milliseconds){
|
| 95 |
+
break;
|
| 96 |
+
}
|
| 97 |
+
}
|
| 98 |
+
}
|
| 99 |
+
|
| 100 |
+
function empty() {
|
| 101 |
+
console.log("empty");
|
| 102 |
+
var def = new jQuery.Deferred();
|
| 103 |
+
clearTimeout(readInsideConllTimeout);
|
| 104 |
+
treelines = [];
|
| 105 |
+
$('#svgwell').html('');
|
| 106 |
+
def.resolve();
|
| 107 |
+
return def.promise();
|
| 108 |
+
}
|
| 109 |
+
|
| 110 |
+
|
| 111 |
+
function progressiveReadConll() {
|
| 112 |
+
// draw each conll tags progressively (only conll tags)
|
| 113 |
+
var conllLoop = d3.selectAll('conll')['_groups'][0]; // need to go out d3js to load it progressively
|
| 114 |
+
var i = 0;
|
| 115 |
+
function waitBetweenElements(range) {
|
| 116 |
+
readConllTimeout = setTimeout(function () {
|
| 117 |
+
|
| 118 |
+
drawConll(conllLoop[i]);
|
| 119 |
+
i++;
|
| 120 |
+
if (i < range) {
|
| 121 |
+
waitBetweenElements(range);
|
| 122 |
+
}
|
| 123 |
+
}, 10)
|
| 124 |
+
}
|
| 125 |
+
|
| 126 |
+
waitBetweenElements(conllLoop.length);
|
| 127 |
+
}
|
| 128 |
+
|
| 129 |
+
function progressiveReadInsideConll(trees, pnode) {
|
| 130 |
+
// draw each tree INSIDE a conll progressively
|
| 131 |
+
var iWait = 0;
|
| 132 |
+
function waitBetweenElements(range) {
|
| 133 |
+
readInsideConllTimeout = setTimeout(function () {
|
| 134 |
+
|
| 135 |
+
pushAndDrawSVG(trees[iWait], pnode);
|
| 136 |
+
|
| 137 |
+
iWait++;
|
| 138 |
+
if (iWait < range) {
|
| 139 |
+
waitBetweenElements(range);
|
| 140 |
+
}
|
| 141 |
+
}, 10)
|
| 142 |
+
}
|
| 143 |
+
waitBetweenElements(trees.length);
|
| 144 |
+
}
|
| 145 |
+
|
| 146 |
+
function pushAndDrawSVG(element, pnode) {
|
| 147 |
+
conlltrees.push(element);
|
| 148 |
+
var data=conllNodesToTree(element);
|
| 149 |
+
trees.push(data.tree);
|
| 150 |
+
uextras.push(data.uextra)
|
| 151 |
+
|
| 152 |
+
// add the save png button according to boolean option (default = false)
|
| 153 |
+
if(pngBtn){
|
| 154 |
+
var btn = pnode.insert('button').attr("class", "btn btn-primary").attr("id", "pngbtn"+svgIdIndex).html('Save PNG');
|
| 155 |
+
$("#pngbtn"+svgIdIndex).click(function(){
|
| 156 |
+
console.log("svgIdIndex",this.id);
|
| 157 |
+
savePng(this.id);
|
| 158 |
+
});
|
| 159 |
+
}
|
| 160 |
+
|
| 161 |
+
if(svgBtn){
|
| 162 |
+
var btn = pnode.insert('button').attr("class", "btn btn-success").attr("id", "svgbtn"+svgIdIndex).html('Save SVG');
|
| 163 |
+
$("#svgbtn"+svgIdIndex).click(function(){
|
| 164 |
+
console.log("svgIdIndex",this.id);
|
| 165 |
+
saveSvg(this.id);
|
| 166 |
+
});
|
| 167 |
+
}
|
| 168 |
+
|
| 169 |
+
|
| 170 |
+
|
| 171 |
+
var divsvgbox = pnode.insert('div').attr("class", 'svgbox');
|
| 172 |
+
divsvgbox.insert('div').html(data.sentence).attr("class", 'sentencebox');
|
| 173 |
+
draw(divsvgbox, data.tree);
|
| 174 |
+
|
| 175 |
+
svgIdIndex=svgIdIndex +1;
|
| 176 |
+
}
|
| 177 |
+
|
| 178 |
+
|
| 179 |
+
|
| 180 |
+
|
| 181 |
+
|
| 182 |
+
function readConll() {
|
| 183 |
+
// reads the conll representation of the whole treebank that is in the conll field
|
| 184 |
+
|
| 185 |
+
trees=[]; // list of tree objects
|
| 186 |
+
uextras=[]; // list of comments. each comment is a hashtable position(=line)->comment # TODO: show sentence features!
|
| 187 |
+
conlltrees=[]; // list of conll strings, one string per tree
|
| 188 |
+
|
| 189 |
+
$('conll').hide(); // to hide the huge conll data
|
| 190 |
+
|
| 191 |
+
if(progressiveLoading){
|
| 192 |
+
progressiveReadConll(); // progressive draw
|
| 193 |
+
}else{
|
| 194 |
+
d3.selectAll('conll').each(function(d){ drawConll(this); }); // all at once
|
| 195 |
+
}
|
| 196 |
+
|
| 197 |
+
// TODO: check whether this is useful: adapt which nodes should be shown depending on what we find on the first node
|
| 198 |
+
// TODO : make it faster. This part is really slow
|
| 199 |
+
/*firstnode=trees[0][Math.min.apply(Math,Object.keys(trees[0]))]; // take lowest existing treenode number
|
| 200 |
+
shownfeatures = $.grep(shownfeatures, function (attri,i)
|
| 201 |
+
{ // for each shownfeatures :
|
| 202 |
+
if (i < 2 || ((attri in firstnode) && firstnode[attri]!=defaultCat)) {
|
| 203 |
+
// either the first two (token and cat) or non default value:
|
| 204 |
+
return true; // keep it
|
| 205 |
+
}
|
| 206 |
+
return false; // kick it out
|
| 207 |
+
});*/
|
| 208 |
+
}
|
| 209 |
+
|
| 210 |
+
function drawConll(conllElement) { // for each <conll> section:
|
| 211 |
+
var conll = d3.select(conllElement).attr("class", 'conll');
|
| 212 |
+
conll.html(conll.html().trim())
|
| 213 |
+
var pnode = d3.select(conllElement.parentNode);
|
| 214 |
+
var toggle = false;
|
| 215 |
+
pnode.insert('a').html('<img src="'+base64Logo+'" alt="Arborator" title="arborator" class="arboratorlogo">').attr('href', 'https://arborator.github.io/').attr('target', '_blank');
|
| 216 |
+
var showHideConll = pnode.insert('div').html('<div class="center" fit>VIEW CONLL</div> <paper-ripple fit></paper-ripple>').attr("class", 'button raised');
|
| 217 |
+
|
| 218 |
+
// <div class="button raised"> <div class="center" fit>SUBMIT</div> <paper-ripple fit></paper-ripple> </div>
|
| 219 |
+
|
| 220 |
+
var conllContent = conll.html().trim();
|
| 221 |
+
conll.remove(); // remove the old conll because it's place wasn't good
|
| 222 |
+
conll = pnode.insert('conll').html(conllContent).attr('class', 'conll'); //re insert to bind the content
|
| 223 |
+
|
| 224 |
+
|
| 225 |
+
showHideConll.on("click", ()=>{
|
| 226 |
+
log(111,toggle);
|
| 227 |
+
conll.style("display", toggle ? "none" : "block");
|
| 228 |
+
showHideConll.html(toggle ? '<div class="center" fit>VIEW CONLL</div> <paper-ripple fit></paper-ripple>': '<div class="center" fit>HIDE CONLL</div> <paper-ripple fit></paper-ripple>');
|
| 229 |
+
toggle = !toggle;
|
| 230 |
+
});
|
| 231 |
+
|
| 232 |
+
|
| 233 |
+
treelines = conll.html().trim().split(/\n\s*\n\s*\n*/);
|
| 234 |
+
|
| 235 |
+
if(progressiveLoading){
|
| 236 |
+
progressiveReadInsideConll(treelines, pnode);
|
| 237 |
+
}else{
|
| 238 |
+
for (let singleConll of treelines) { // for each conll tree at once, can block the browser
|
| 239 |
+
pushAndDrawSVG(singleConll, pnode);
|
| 240 |
+
}
|
| 241 |
+
}
|
| 242 |
+
|
| 243 |
+
}
|
| 244 |
+
|
| 245 |
+
|
| 246 |
+
function conllNodesToTree(treeline) {
|
| 247 |
+
// reads a conll representation of a single tree TODO: replace jquery by d3
|
| 248 |
+
|
| 249 |
+
var nodes = treeline.split('\n');
|
| 250 |
+
if(reverseMode)nodes.reverse();
|
| 251 |
+
// nodes = nodes.reverse();
|
| 252 |
+
var tree={};
|
| 253 |
+
var uextra={};
|
| 254 |
+
var lastid=0;
|
| 255 |
+
var skipuntil=0;
|
| 256 |
+
var words=[]
|
| 257 |
+
$.each(nodes, function(id,nodeline){ // for each conll line:
|
| 258 |
+
var nodeline=$.trim(nodeline);
|
| 259 |
+
if (nodeline.charAt(0) == "#") {
|
| 260 |
+
if (!(lastid in uextra)) uextra[lastid]=[];
|
| 261 |
+
uextra[lastid].push(nodeline)
|
| 262 |
+
return true;
|
| 263 |
+
}
|
| 264 |
+
var elements = nodeline.split('\t');
|
| 265 |
+
el=elements.length;
|
| 266 |
+
|
| 267 |
+
if (!(el in conlls) && el>10) el=10;
|
| 268 |
+
if (el > 4) id=elements[conlls[el]["id"]];
|
| 269 |
+
else if (elements[conlls[el]["t"]] != "_") id++;
|
| 270 |
+
if (lastid!=id) // needed for the arborator encoding of multiple govs
|
| 271 |
+
{
|
| 272 |
+
var t=elements[conlls[el]["t"]];
|
| 273 |
+
var tokids=id.split("-")
|
| 274 |
+
if (tokids.length == 1) {
|
| 275 |
+
tree[id]={}
|
| 276 |
+
tree[id]["gov"]={};
|
| 277 |
+
tree[id]["t"]=t;
|
| 278 |
+
tree[id]["id"]=id;
|
| 279 |
+
tree[id]["lemma"]=elements[conlls[el]["lemma"]];
|
| 280 |
+
tree[id]["cat"]=elements[conlls[el]["cat"]];
|
| 281 |
+
if (id>skipuntil) words.push(t);
|
| 282 |
+
if (el==10) {
|
| 283 |
+
tree[id]["xpos"]=elements[conlls[el]["xpos"]];
|
| 284 |
+
tree[id]["morph"]=elements[conlls[el]["morph"]];
|
| 285 |
+
tree[id]["gloss"]=elements[conlls[el]["gloss"]];
|
| 286 |
+
if (tree[id]["gloss"]=="SpaceAfter=No"){
|
| 287 |
+
tree[id]["gloss"]="_";
|
| 288 |
+
tree[id]["NoSpaceAfter"]=false;
|
| 289 |
+
}
|
| 290 |
+
var xgov = elements[conlls[el]["xgov"]];
|
| 291 |
+
if (xgov.indexOf(':') > -1){
|
| 292 |
+
var xgovs=xgov.split("|");
|
| 293 |
+
$.each(xgovs, function(ind,xg){
|
| 294 |
+
// for each extra governor line:
|
| 295 |
+
var xgs=xg.split(":")
|
| 296 |
+
if (xgs.length >=2) {
|
| 297 |
+
// if it's not just _
|
| 298 |
+
var gov=xgs[0];
|
| 299 |
+
var func= xgs.slice(1).join(":");
|
| 300 |
+
tree[id]["gov"][gov]=func;
|
| 301 |
+
}
|
| 302 |
+
});
|
| 303 |
+
}
|
| 304 |
+
}
|
| 305 |
+
}
|
| 306 |
+
else if (tokids.length == 2){
|
| 307 |
+
skipuntil = parseInt(tokids[1])
|
| 308 |
+
words.push(elements[conlls[el]["t"]]);
|
| 309 |
+
if (!(lastid in uextra)) uextra[lastid]=[];
|
| 310 |
+
uextra[lastid].push(nodeline)
|
| 311 |
+
}
|
| 312 |
+
else {
|
| 313 |
+
if (!(lastid in uextra)) uextra[lastid]=[];
|
| 314 |
+
uextra[lastid].push(nodeline)
|
| 315 |
+
}
|
| 316 |
+
}
|
| 317 |
+
gov = elements[conlls[el]["gov"]];
|
| 318 |
+
if (gov!="" && gov!="_")
|
| 319 |
+
{
|
| 320 |
+
if (gov==-1)
|
| 321 |
+
{
|
| 322 |
+
gov = elements[conlls[el]["gov"]+1];
|
| 323 |
+
}
|
| 324 |
+
var func = elements[conlls[el]["func"]];
|
| 325 |
+
if (func.indexOf('::') !== -1)
|
| 326 |
+
{
|
| 327 |
+
var stydic = func.substring(func.indexOf("::") + 1);
|
| 328 |
+
func = func.split("::")[0];
|
| 329 |
+
if (stydic!="") funcDic[func] = $.parseJSON(stydic);
|
| 330 |
+
$('#styleconllcheck').prop('checked', true);
|
| 331 |
+
};
|
| 332 |
+
tree[id]["gov"][gov]=func;
|
| 333 |
+
|
| 334 |
+
}
|
| 335 |
+
lastid=id;
|
| 336 |
+
});
|
| 337 |
+
|
| 338 |
+
|
| 339 |
+
var sentence="";
|
| 340 |
+
words.forEach(function (word, i) {
|
| 341 |
+
sentence+=word;
|
| 342 |
+
if(!reverseMode){
|
| 343 |
+
if (i+1 in tree && !(("NoSpaceAfter" in tree[i+1]) && tree[i+1]["NoSpaceAfter"]==false)) sentence+=" ";
|
| 344 |
+
}else{
|
| 345 |
+
sentence+=" ";
|
| 346 |
+
}
|
| 347 |
+
});
|
| 348 |
+
return {tree:tree, uextra:uextra, sentence:sentence};
|
| 349 |
+
}
|
| 350 |
+
|
| 351 |
+
|
| 352 |
+
function getSVGPath(startPoint,endPoint,computedStyle) {
|
| 353 |
+
// startPoint and endPoint are objects for the corresponding nodes
|
| 354 |
+
|
| 355 |
+
var tokDepDist = parseInt(computedStyle.getPropertyValue('--tokDepDist'));
|
| 356 |
+
var depMinHeight = parseInt(computedStyle.getPropertyValue('--depMinHeight'));
|
| 357 |
+
var wordDistanceFactor = parseInt(computedStyle.getPropertyValue('--wordDistanceFactor'));
|
| 358 |
+
if(reverseMode) wordDistanceFactor = -Math.abs(wordDistanceFactor);
|
| 359 |
+
var startOffset = parseInt(computedStyle.getPropertyValue('--startOffset'));
|
| 360 |
+
if(reverseMode) startOffset = -Math.abs(startOffset);
|
| 361 |
+
var startOff=(startPoint['id']-endPoint['id']>0)?-startOffset:startOffset
|
| 362 |
+
var x1 = startPoint['x']+startPoint['w']/2+startOff;
|
| 363 |
+
var x2 = endPoint['x']+endPoint['w']/2;
|
| 364 |
+
var y1 = svgDefaultHeight-fontSize*2;
|
| 365 |
+
var y2 = svgDefaultHeight-fontSize*2;
|
| 366 |
+
var x1x2=Math.abs(x1-x2)/2;
|
| 367 |
+
var yy = Math.max(y1-x1x2-wordDistanceFactor*Math.abs(endPoint['id']-startPoint['id']),-tokDepDist);
|
| 368 |
+
var yy = Math.min(yy,y1)-depMinHeight;
|
| 369 |
+
var cstr="M"+x1+","+y1+" C"+x1+","+yy+" "+x2+","+yy+" "+x2+","+(y2-2); // -2 so that the arrow is really pointed
|
| 370 |
+
//(x0,y0) is start point; (x1,y1),(x2,y2) is control points; (x3,y3) is end point.
|
| 371 |
+
return {cstr:cstr, x0:x1,y0:y1, x1:x1,y1:yy, x2:x2,y2:yy,x3:x2,y3:(y2-2)};
|
| 372 |
+
}
|
| 373 |
+
|
| 374 |
+
|
| 375 |
+
function arrowhead(x,y) {
|
| 376 |
+
// gives path for arrowhead x,y startpoint (end of arrow)
|
| 377 |
+
var size = 5;
|
| 378 |
+
var startpoint = x+","+y; // to move the arrowhead lower: (y+size/3);
|
| 379 |
+
var lefttop = "0,0" +(-size/2)+","+(-size*1.5)+" "+(-size/2)+","+(-size*1.5);
|
| 380 |
+
var righttop = (size/2)+"," +(size/2)+" "+(size/2)+"," +(size/2)+ " "+(size)+",0";
|
| 381 |
+
var arrowPath = "M"+ startpoint+"c"+lefttop+ "c"+righttop+ "z";
|
| 382 |
+
return arrowPath;
|
| 383 |
+
}
|
| 384 |
+
|
| 385 |
+
|
| 386 |
+
function draw(div, tree) {
|
| 387 |
+
// draws json tree on svg in div
|
| 388 |
+
|
| 389 |
+
var runningWidth = 0;
|
| 390 |
+
var smallestY = svgDefaultHeight;
|
| 391 |
+
var treeArray = $.map(tree, function(value, index) {return [value];});
|
| 392 |
+
var svg = div.append("svg:svg")
|
| 393 |
+
.attr("width", 1000)
|
| 394 |
+
.attr("height", svgDefaultHeight);
|
| 395 |
+
var group = svg.append("g");
|
| 396 |
+
// write tokens:
|
| 397 |
+
if(reverseMode) treeArray.reverse();
|
| 398 |
+
var eachTexts = group.selectAll("text")
|
| 399 |
+
.data(treeArray)
|
| 400 |
+
.enter();
|
| 401 |
+
|
| 402 |
+
|
| 403 |
+
var runningWidth2 = 0;
|
| 404 |
+
|
| 405 |
+
eachTexts.append('text')
|
| 406 |
+
.attr("class", "token")
|
| 407 |
+
.text(function(d){return d["t"];})
|
| 408 |
+
.attr("id",function(d) {return d["id"];})
|
| 409 |
+
.attr("x", function(d) {
|
| 410 |
+
var w = this.getComputedTextLength();
|
| 411 |
+
wordDistance = parseInt(getComputedStyle(this).getPropertyValue('--wordDistance'));
|
| 412 |
+
var x = runningWidth; //<-- previous length to return
|
| 413 |
+
runningWidth += w + wordDistance; //<-- total
|
| 414 |
+
tree[d["id"]]["x"]=x;
|
| 415 |
+
tree[d["id"]]["w"]=w;
|
| 416 |
+
fontSize = parseInt(getComputedStyle(this).fontSize, 10);
|
| 417 |
+
return x;
|
| 418 |
+
})
|
| 419 |
+
.attr("y", svgDefaultHeight-fontSize);
|
| 420 |
+
|
| 421 |
+
svg.attr("width", runningWidth); // adapt svg width
|
| 422 |
+
|
| 423 |
+
// draw dependency links
|
| 424 |
+
group.selectAll("text").each(function(d) { // for each token:
|
| 425 |
+
var txt = d3.select(this);
|
| 426 |
+
for (var govid in tree[d3.select(this).attr("id")]["gov"]) { // for each governor
|
| 427 |
+
x=tree[txt.attr("id")]['x']+tree[txt.attr("id")]['w']/2;
|
| 428 |
+
var ligneDep = group.append("path")
|
| 429 |
+
.attr("class", "curve")
|
| 430 |
+
.attr("d", function (dd) {
|
| 431 |
+
if (govid==0) // sentence root:
|
| 432 |
+
{
|
| 433 |
+
var y=svgDefaultHeight-fontSize*2;
|
| 434 |
+
return "M"+x+","+(y-2)+"L"+x+","+0; // -2 so that the arrow is really pointed
|
| 435 |
+
}
|
| 436 |
+
else // normal link:
|
| 437 |
+
{
|
| 438 |
+
pathInfo=getSVGPath(tree[govid],tree[txt.attr("id")], getComputedStyle(this))
|
| 439 |
+
return pathInfo.cstr ;
|
| 440 |
+
}
|
| 441 |
+
|
| 442 |
+
});
|
| 443 |
+
group.append("path")
|
| 444 |
+
.attr("class", "arrowhead")
|
| 445 |
+
.attr("d", function (dd) {
|
| 446 |
+
return arrowhead(x, svgDefaultHeight - fontSize*2);
|
| 447 |
+
});
|
| 448 |
+
var label=tree[d3.select(this).attr("id")]["gov"][govid];
|
| 449 |
+
var depLineBbox=ligneDep.node().getBBox();
|
| 450 |
+
|
| 451 |
+
// TODO: move the "root" label to a good position! (possibly to a group that has to be transformed separately!)
|
| 452 |
+
// TODO: handle mutliple governors!
|
| 453 |
+
if (govid!=0) // normal link:
|
| 454 |
+
{
|
| 455 |
+
group.append('text')
|
| 456 |
+
.attr("class", "deprel")
|
| 457 |
+
.text(function(d){return label})
|
| 458 |
+
.attr("x", function(d) {
|
| 459 |
+
relFontSize = parseInt(getComputedStyle(this).fontSize, 10);
|
| 460 |
+
var w = this.getComputedTextLength(); //<-- length of this node
|
| 461 |
+
return depLineBbox.x + depLineBbox.width/2 - w/2})
|
| 462 |
+
.attr("y", function(d) {
|
| 463 |
+
funcCurveDist = parseInt(getComputedStyle(this).getPropertyValue('--funcCurveDist'));
|
| 464 |
+
if (isFirefox)
|
| 465 |
+
{
|
| 466 |
+
// firefox needs: stackoverflow.com/questions/24809978/calculating-the-bounding-box-of-cubic-bezier-curve
|
| 467 |
+
const {x0, y0, x1, y1, x2, y2, x3, y3} = pathInfo // firefox
|
| 468 |
+
y = bezierMinMax(x0, y0, x1, y1, x2, y2, x3, y3).min.y-funcCurveDist;
|
| 469 |
+
return y; // firefox
|
| 470 |
+
}
|
| 471 |
+
else
|
| 472 |
+
{
|
| 473 |
+
// standard Chrome etc
|
| 474 |
+
y = depLineBbox.y-funcCurveDist
|
| 475 |
+
return y;
|
| 476 |
+
}
|
| 477 |
+
})
|
| 478 |
+
// if not root, check how high we got:
|
| 479 |
+
var smallY = y-relFontSize
|
| 480 |
+
smallestY = smallY < smallestY ? smallY : smallestY;
|
| 481 |
+
|
| 482 |
+
}
|
| 483 |
+
}
|
| 484 |
+
// txt.on("click", started);
|
| 485 |
+
txt.on("drag", function(d){console.log('draggg')});
|
| 486 |
+
});
|
| 487 |
+
|
| 488 |
+
|
| 489 |
+
// write lemmas
|
| 490 |
+
eachTexts.append('text')
|
| 491 |
+
.attr("class", "lemma")
|
| 492 |
+
.text(function(d){return d["lemma"];})
|
| 493 |
+
.attr("id",function(d) {return d["id"];})
|
| 494 |
+
.attr("x", function(d) {
|
| 495 |
+
var lemmaLength = this.getComputedTextLength();
|
| 496 |
+
var w = tree[d["id"]]["w"];
|
| 497 |
+
wordDistance = parseInt(getComputedStyle(this).getPropertyValue('--wordDistance'));
|
| 498 |
+
var x = tree[d["id"]]["x"] ; //<-- previous length to return
|
| 499 |
+
lemmaHeight = parseInt(getComputedStyle(this).fontSize, 20);
|
| 500 |
+
return x;
|
| 501 |
+
})
|
| 502 |
+
.attr("y", svgDefaultHeight-fontSize+lemmaHeight);
|
| 503 |
+
|
| 504 |
+
// write pos
|
| 505 |
+
eachTexts.append('text')
|
| 506 |
+
.attr("class", "postag")
|
| 507 |
+
.text(function(d){return d["cat"];})
|
| 508 |
+
.attr("id",function(d) {return d["id"];})
|
| 509 |
+
.attr("x", function(d) {
|
| 510 |
+
var posLength = this.getComputedTextLength();
|
| 511 |
+
var w = tree[d["id"]]["w"];
|
| 512 |
+
wordDistance = parseInt(getComputedStyle(this).getPropertyValue('--wordDistance'));
|
| 513 |
+
if(posLength>w+10){
|
| 514 |
+
var x = tree[d["id"]]["x"] - posLength/3 ; //<-- previous length to return
|
| 515 |
+
}else{
|
| 516 |
+
var x = tree[d["id"]]["x"] ; //<-- previous length to return
|
| 517 |
+
}
|
| 518 |
+
posHeight = parseInt(getComputedStyle(this).fontSize, 20);
|
| 519 |
+
return x;
|
| 520 |
+
})
|
| 521 |
+
.attr("y", svgDefaultHeight-fontSize+lemmaHeight+posHeight);
|
| 522 |
+
|
| 523 |
+
|
| 524 |
+
group.attr("transform", "translate(" + 0 + "," + (-smallestY) + ")");
|
| 525 |
+
svg.attr("height", svgDefaultHeight-smallestY+posHeight+lemmaHeight+fontSize); // adapt svg height
|
| 526 |
+
|
| 527 |
+
svg.attr("id", "svg"+svgIdIndex);
|
| 528 |
+
svg.attr("version", '1.1'); // to prepare ddl of svg
|
| 529 |
+
svg.attr("xmlns", "http://www.w3.org/2000/svg"); // to prepare ddl of svg
|
| 530 |
+
}
|
| 531 |
+
|
| 532 |
+
|
| 533 |
+
//(x0,y0) is start point; (x1,y1),(x2,y2) is control points; (x3,y3) is end point.
|
| 534 |
+
function bezierMinMax(x0, y0, x1, y1, x2, y2, x3, y3) {
|
| 535 |
+
var tvalues = [], xvalues = [], yvalues = [],
|
| 536 |
+
a, b, c, t, t1, t2, b2ac, sqrtb2ac;
|
| 537 |
+
for (var i = 0; i < 2; ++i) {
|
| 538 |
+
if (i == 0) {
|
| 539 |
+
b = 6 * x0 - 12 * x1 + 6 * x2;
|
| 540 |
+
a = -3 * x0 + 9 * x1 - 9 * x2 + 3 * x3;
|
| 541 |
+
c = 3 * x1 - 3 * x0;
|
| 542 |
+
} else {
|
| 543 |
+
b = 6 * y0 - 12 * y1 + 6 * y2;
|
| 544 |
+
a = -3 * y0 + 9 * y1 - 9 * y2 + 3 * y3;
|
| 545 |
+
c = 3 * y1 - 3 * y0;
|
| 546 |
+
}
|
| 547 |
+
if (Math.abs(a) < 1e-12) {
|
| 548 |
+
if (Math.abs(b) < 1e-12) {
|
| 549 |
+
continue;
|
| 550 |
+
}
|
| 551 |
+
t = -c / b;
|
| 552 |
+
if (0 < t && t < 1) {
|
| 553 |
+
tvalues.push(t);
|
| 554 |
+
}
|
| 555 |
+
continue;
|
| 556 |
+
}
|
| 557 |
+
b2ac = b * b - 4 * c * a;
|
| 558 |
+
if (b2ac < 0) {
|
| 559 |
+
continue;
|
| 560 |
+
}
|
| 561 |
+
sqrtb2ac = Math.sqrt(b2ac);
|
| 562 |
+
t1 = (-b + sqrtb2ac) / (2 * a);
|
| 563 |
+
if (0 < t1 && t1 < 1) {
|
| 564 |
+
tvalues.push(t1);
|
| 565 |
+
}
|
| 566 |
+
t2 = (-b - sqrtb2ac) / (2 * a);
|
| 567 |
+
if (0 < t2 && t2 < 1) {
|
| 568 |
+
tvalues.push(t2);
|
| 569 |
+
}
|
| 570 |
+
}
|
| 571 |
+
|
| 572 |
+
var j = tvalues.length, mt;
|
| 573 |
+
while (j--) {
|
| 574 |
+
t = tvalues[j];
|
| 575 |
+
mt = 1 - t;
|
| 576 |
+
xvalues[j] = (mt * mt * mt * x0) + (3 * mt * mt * t * x1) + (3 * mt * t * t * x2) + (t * t * t * x3);
|
| 577 |
+
yvalues[j] = (mt * mt * mt * y0) + (3 * mt * mt * t * y1) + (3 * mt * t * t * y2) + (t * t * t * y3);
|
| 578 |
+
}
|
| 579 |
+
|
| 580 |
+
xvalues.push(x0,x3);
|
| 581 |
+
yvalues.push(y0,y3);
|
| 582 |
+
|
| 583 |
+
return {
|
| 584 |
+
min: {x: Math.min.apply(0, xvalues), y: Math.min.apply(0, yvalues)},
|
| 585 |
+
max: {x: Math.max.apply(0, xvalues), y: Math.max.apply(0, yvalues)}
|
| 586 |
+
};
|
| 587 |
+
}
|
| 588 |
+
|
| 589 |
+
function svg2Data(svg) {
|
| 590 |
+
var tempCSS = document.createElement("style");
|
| 591 |
+
tempCSS.innerHTML = '.token { font: 18px DejaVu Sans; fill: black; font-family:sans-serif; text-align: center; } .lemma { font: 15px DejaVu Sans; fill: black; font-family:sans-serif; text-align: center; font-style: italic; } .postag { font: 11px DejaVu Sans; fill: #E03737; text-align: center; } .deprel { font: 12px Arial; fill: #1d2ec1; font-style: oblique; font-family:sans-serif; } .arrowhead { fill: white; stroke: black; stroke-width: .8; } .curve { stroke: black; stroke-width: 1; fill: none; .arboratorlogo { transition: all 0.4s ease-in-out; -webkit-transition: all 0.4s ease-in-out; } .arboratorlogo:hover { transform: scale(1.1); transition: all 0.2s ease-in-out; -webkit-transition: all 0.2s ease-in-out; opacity: .9; } .svgbox { overflow-x: auto; }"';
|
| 592 |
+
svg.appendChild(tempCSS);
|
| 593 |
+
return svg.outerHTML;
|
| 594 |
+
}
|
| 595 |
+
|
| 596 |
+
function png2Data(svg) {
|
| 597 |
+
var canvas = document.createElement('canvas');
|
| 598 |
+
var tempCSS = document.createElement("style");
|
| 599 |
+
tempCSS.innerHTML = '.token { font: 18px DejaVu Sans; fill: black; font-family:sans-serif; text-align: center; } .lemma { font: 15px DejaVu Sans; fill: black; font-family:sans-serif; text-align: center; font-style: italic; } .postag { font: 11px DejaVu Sans; fill: #E03737; text-align: center; } .deprel { font: 12px Arial; fill: #1d2ec1; font-style: oblique; font-family:sans-serif; } .arrowhead { fill: white; stroke: black; stroke-width: .8; } .curve { stroke: black; stroke-width: 1; fill: none;}';
|
| 600 |
+
svg.insertBefore(tempCSS, svg.firstChild); // === the missing prepend option
|
| 601 |
+
|
| 602 |
+
var bb = svg.getBBox();
|
| 603 |
+
// canvas.height = bb.height*5;
|
| 604 |
+
// canvas.width = bb.width*5;
|
| 605 |
+
// svg.width = svg.width*3;
|
| 606 |
+
// svg.height = svg.height*3;
|
| 607 |
+
// svg.setAttribute('width', bb.width*5);
|
| 608 |
+
// svg.setAttribute('height', bb.height*5);
|
| 609 |
+
var data = (new XMLSerializer()).serializeToString(svg);
|
| 610 |
+
console.log('svgData', data);
|
| 611 |
+
canvg(canvas, data);
|
| 612 |
+
return canvas.toDataURL().replace('data:image/png;base64,','');
|
| 613 |
+
|
| 614 |
+
}
|
| 615 |
+
|
| 616 |
+
function savePng(btnId) {
|
| 617 |
+
var id = btnId.replace("pngbtn","");
|
| 618 |
+
var canvas = document.createElement('canvas');
|
| 619 |
+
var tempCSS = document.createElement("style");
|
| 620 |
+
tempCSS.innerHTML = '.token { font: 18px DejaVu Sans; fill: black; font-family:sans-serif; text-align: center; } .lemma { font: 15px DejaVu Sans; fill: black; font-family:sans-serif; text-align: center; font-style: italic; } .postag { font: 11px DejaVu Sans; fill: #E03737; text-align: center; } .deprel { font: 12px Arial; fill: #1d2ec1; font-style: oblique; font-family:sans-serif; } .arrowhead { fill: white; stroke: black; stroke-width: .8; } .curve { stroke: black; stroke-width: 1; fill: none;}';
|
| 621 |
+
var svg = document.getElementById("svg"+id);
|
| 622 |
+
svg.appendChild(tempCSS);
|
| 623 |
+
var bb = svg.getBBox();
|
| 624 |
+
canvas.height = bb.height*5;
|
| 625 |
+
canvas.width = bb.width*5;
|
| 626 |
+
var ctx = canvas.getContext('2d');
|
| 627 |
+
var data = (new XMLSerializer()).serializeToString(svg);
|
| 628 |
+
var DOMURL = window.URL || window.webkitURL || window;
|
| 629 |
+
var img = new Image();
|
| 630 |
+
var svgBlob = new Blob([data], {type: 'image/svg+xml;charset=utf-8'});
|
| 631 |
+
var url = DOMURL.createObjectURL(svgBlob);
|
| 632 |
+
img.onload = function () {
|
| 633 |
+
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);//, 0, 0, ctx.width, ctx.height);
|
| 634 |
+
DOMURL.revokeObjectURL(url);
|
| 635 |
+
var imgURI = canvas
|
| 636 |
+
.toDataURL('image/png')
|
| 637 |
+
.replace('image/png', 'image/octet-stream');
|
| 638 |
+
var evt = new MouseEvent('click', {
|
| 639 |
+
view: window,
|
| 640 |
+
bubbles: false,
|
| 641 |
+
cancelable: true
|
| 642 |
+
});
|
| 643 |
+
var a = document.createElement('a');
|
| 644 |
+
a.setAttribute('download', 'svg'+id+'.png');
|
| 645 |
+
a.setAttribute('href', imgURI );
|
| 646 |
+
a.setAttribute('target', '_blank');
|
| 647 |
+
a.dispatchEvent(evt);
|
| 648 |
+
};
|
| 649 |
+
img.src = url;
|
| 650 |
+
}
|
| 651 |
+
|
| 652 |
+
function saveSvg(btnId) {
|
| 653 |
+
console.log(btnId);
|
| 654 |
+
var id = btnId.replace("svgbtn","");
|
| 655 |
+
var canvas = document.createElement('canvas');
|
| 656 |
+
console.log("canvas", canvas);
|
| 657 |
+
|
| 658 |
+
|
| 659 |
+
var tempCSS = document.createElement("style");
|
| 660 |
+
tempCSS.innerHTML = '.token { font: 18px DejaVu Sans; fill: black; font-family:sans-serif; text-align: center; } .lemma { font: 15px DejaVu Sans; fill: black; font-family:sans-serif; text-align: center; font-style: italic; } .postag { font: 11px DejaVu Sans; fill: #E03737; text-align: center; } .deprel { font: 12px Arial; fill: #1d2ec1; font-style: oblique; font-family:sans-serif; } .arrowhead { fill: white; stroke: black; stroke-width: .8; } .curve { stroke: black; stroke-width: 1; fill: none; .arboratorlogo { transition: all 0.4s ease-in-out; -webkit-transition: all 0.4s ease-in-out; } .arboratorlogo:hover { transform: scale(1.1); transition: all 0.2s ease-in-out; -webkit-transition: all 0.2s ease-in-out; opacity: .9; } .svgbox { overflow-x: auto; }" width="1140" height="470.1878970357652"';
|
| 661 |
+
|
| 662 |
+
var svg = document.getElementById("svg"+id);
|
| 663 |
+
svg.appendChild(tempCSS);
|
| 664 |
+
|
| 665 |
+
var svgData = svg.outerHTML;
|
| 666 |
+
var svgBlob = new Blob([svgData], {type:"image/svg+xml;charset=utf-8"});
|
| 667 |
+
var svgUrl = URL.createObjectURL(svgBlob);
|
| 668 |
+
var downloadLink = document.createElement("a");
|
| 669 |
+
downloadLink.href = svgUrl;
|
| 670 |
+
downloadLink.download = "treeSvg"+id+".svg";
|
| 671 |
+
document.body.appendChild(downloadLink);
|
| 672 |
+
downloadLink.click();
|
| 673 |
+
document.body.removeChild(downloadLink);
|
| 674 |
+
|
| 675 |
+
}
|
| 676 |
+
|
| 677 |
+
|
| 678 |
+
function exportPngZip() {
|
| 679 |
+
var zip = new JSZip();
|
| 680 |
+
var folder = zip.folder("pngfiles");
|
| 681 |
+
var svgList = $('svg');
|
| 682 |
+
var svgD3List = window.d3.selectAll("svg");
|
| 683 |
+
console.log(2222,svgD3List);
|
| 684 |
+
$.each( svgD3List['_groups'][0], function( index, value ){
|
| 685 |
+
console.log('value', index, value);
|
| 686 |
+
var pngData = png2Data(value);
|
| 687 |
+
folder.file('tree'+value.id+'.png', pngData, {base64: true});
|
| 688 |
+
});
|
| 689 |
+
zip.generateAsync({type:"blob"})
|
| 690 |
+
.then(function(content) {
|
| 691 |
+
saveAs(content, "export.zip");
|
| 692 |
+
});
|
| 693 |
+
}
|
| 694 |
+
|
| 695 |
+
function exportSvgZip() {
|
| 696 |
+
var zip = new JSZip();
|
| 697 |
+
var folder = zip.folder("svgfiles");
|
| 698 |
+
var svgList = $('svg');
|
| 699 |
+
$.each( svgList, function( index, value ){
|
| 700 |
+
var svgData = svg2Data(value);
|
| 701 |
+
folder.file('tree'+svg.id+'.svg', svgData);
|
| 702 |
+
});
|
| 703 |
+
|
| 704 |
+
zip.generateAsync({type:"blob"})
|
| 705 |
+
.then(function(content) {
|
| 706 |
+
saveAs(content, "export.zip");
|
| 707 |
+
});
|
| 708 |
+
}
|
| 709 |
+
|
| 710 |
+
$("#btnSvgZip").on("click", function (){
|
| 711 |
+
exportSvgZip();
|
| 712 |
+
});
|
| 713 |
+
|
| 714 |
+
$("#btnPngZip").on("click", function (){
|
| 715 |
+
exportPngZip();
|
| 716 |
+
});
|
| 717 |
+
|
| 718 |
+
|
| 719 |
+
}());
|
| 720 |
+
|
src/arborator-draft/arborator.svg
ADDED
|
|
src/arborator-draft/bootstrap.min.css
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
src/arborator-draft/canvg.js
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
src/arborator-draft/d3.js
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
src/arborator-draft/example_arborator-draft.html
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE HTML>
|
| 2 |
+
|
| 3 |
+
<html>
|
| 4 |
+
|
| 5 |
+
<head>
|
| 6 |
+
<meta charset="UTF-8" />
|
| 7 |
+
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
|
| 8 |
+
<link rel="stylesheet" href="bootstrap.min.css">
|
| 9 |
+
<link rel="stylesheet" href="arborator-draft.css" type="text/css" />
|
| 10 |
+
<title>Arborator Draft - Example of visualization of CoNLL-U data</title>
|
| 11 |
+
</head>
|
| 12 |
+
|
| 13 |
+
<body>
|
| 14 |
+
<div class="container">
|
| 15 |
+
|
| 16 |
+
<div style="text-align: center;">
|
| 17 |
+
<svg
|
| 18 |
+
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
| 19 |
+
xmlns:cc="http://creativecommons.org/ns#"
|
| 20 |
+
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
| 21 |
+
xmlns:svg="http://www.w3.org/2000/svg"
|
| 22 |
+
xmlns="http://www.w3.org/2000/svg"
|
| 23 |
+
version="1.1"
|
| 24 |
+
viewBox="-4202 0 5704.1939 1840.839"
|
| 25 |
+
style="image-rendering:optimizeQuality;"
|
| 26 |
+
height="130"
|
| 27 |
+
width="270"
|
| 28 |
+
xml:space="preserve">
|
| 29 |
+
<path
|
| 30 |
+
style="fill:none;stroke:#4a2769;stroke-width:128.73750305;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;"
|
| 31 |
+
d="m -1890.5398,1002.7933 -1822.5445,615.288 c -261.3344,-190.4146 -424.5469,-433.2903 -424.5469,-661.59345 0,-685.88115 1244.2446,-1296.6446 2780.191,-1296.6446 1534.97478,0 2795.2653,610.76345 2795.2653,1296.6446 0,685.88105 -1252.26757,1244.49535 -2787.2424,1244.49535 -239.9613,0 -490.6091,-19.4301 -718.9123,-43.7176 L -751.94297,618.40481 -882.8496,663.4494" /><path
|
| 32 |
+
style="fill:none;stroke:#dd137b;stroke-width:128.73750305;stroke-miterlimit:4;"
|
| 33 |
+
d="M -864.53567,745.22843 C -964.68477,501.46149 -1354.4152,-183.90675 -1694.5756,-3.2652517 -2014.6556,165.68318 -2049.9732,423.17981 -1871.2632,1084.3717 c 67.0564,232.3776 161.3346,398.0135 238.7197,540.6756" /><path
|
| 34 |
+
style="fill:none;stroke:#4a2769;stroke-width:128.73750305;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;"
|
| 35 |
+
d="M -2068.3297,2157.2657 -751.94297,618.40481"
|
| 36 |
+
/>
|
| 37 |
+
</svg>
|
| 38 |
+
</div>
|
| 39 |
+
<div class="row" style="margin-top: 15px;">
|
| 40 |
+
<div class="panel panel-primary" style="border-color: #4a2769;">
|
| 41 |
+
<div class="panel-heading" style="background-color: #4a2769;"><h2 >It's easy to add dependency graphs to your web page</h2></div>
|
| 42 |
+
<div class="panel-body">
|
| 43 |
+
|
| 44 |
+
<ol>
|
| 45 |
+
<li> <strong>Simply put the CoNLL-U data between <conll> tags where you want to show the dependency graph.</strong></li>
|
| 46 |
+
<li><strong>Import arborator-draft.css, arborator-draft.js, d3.js, and jquery.</strong></li>
|
| 47 |
+
<li><strong>Add this in the end of your html page:</strong></li>
|
| 48 |
+
</ol>
|
| 49 |
+
|
| 50 |
+
|
| 51 |
+
<pre><code> window.onload = function () {
|
| 52 |
+
new ArboratorDraft(); // START
|
| 53 |
+
}</code></pre>
|
| 54 |
+
<p><strong>Automatically, the CoNLL-U data will be transformed into beautiful dependency graphs!</strong></p>
|
| 55 |
+
|
| 56 |
+
<p>Graphical options are in arborator-draft.css</p>
|
| 57 |
+
<p>If you want to generally modify which features are shown, modify these lines in the arborator-draft.js:</p>
|
| 58 |
+
<pre><code> shownfeatures=["FORM", "UPOS", "LEMMA", "MISC.Gloss"];
|
| 59 |
+
shownmetas=['text_en']</code></pre>
|
| 60 |
+
<p>If you want to temporarily modify which features are shown, add the shownfeatures attribute to the meta-features of the conll representations, and provide the list of features separated by commas. Morphosyntactic features must be prefixed by FEATS. and miscellaneous features by MISC. as in:</p>
|
| 61 |
+
<pre><code># shownfeatures = FORM, UPOS, LEMMA, MISC.Gloss, FEATS.ExtPos, FEATS.PhraseType, FEATS.InTitle
|
| 62 |
+
</code></pre>
|
| 63 |
+
|
| 64 |
+
<p>If you want to have a button to show the complete conll data (not only per tree), change <code>showAllConllButton</code> to true</p>
|
| 65 |
+
<p>If you want to add those two blue buttons just below to your page, which allow to download the complete set of svg or png images in a zip, add <code>jszip.min.js</code> and <code>FileSaver.min.js</code> to the imports</p>
|
| 66 |
+
|
| 67 |
+
<hr/>
|
| 68 |
+
<p>Please admire the speed of the non-blocking rendering in <a href="speedtest.separateConllTags.html">this file with many separate CoNLL nodes</a> and <a href="speedtest.oneBigConllTag.html">that file with one very long CoNLL node</a></p>
|
| 69 |
+
<p>Todo:
|
| 70 |
+
<ul>
|
| 71 |
+
<li>add sound player if sound_url is present.</li>
|
| 72 |
+
<li>For SVG and PNG download, update automatically the information from the .css file, instead of copying it into the code as defaultcss. See problem at https://stackoverflow.com/questions/3211536/accessing-cross-domain-style-sheet-with-cssrules</li>
|
| 73 |
+
<li>When hanging back in the conll node, fix the order with the neighbors, so that a surrounding div becomes unnecessary.</li>
|
| 74 |
+
|
| 75 |
+
</ul> </p>
|
| 76 |
+
|
| 77 |
+
</div>
|
| 78 |
+
<div class="panel-footer">
|
| 79 |
+
<button id="btnSvgZip" class="btn btn-primary" style="background-color: #4a2769; border-color: #4a2769;">Export SVG files in Zip</button>
|
| 80 |
+
<button id="btnPngZip" class="btn btn-primary" style="background-color: #4a2769; border-color: #4a2769;">Export PNG files in Zip</button>
|
| 81 |
+
</div>
|
| 82 |
+
</div>
|
| 83 |
+
</div>
|
| 84 |
+
|
| 85 |
+
<div class="row">
|
| 86 |
+
<div class="panel panel-primary" style="border-color: #4a2769;">
|
| 87 |
+
<div class="panel-heading" style="background-color: #4a2769; border-color: #4a2769;"><h2>First example of CoNLL-U data surrounded by Conll tags</h2></div>
|
| 88 |
+
<p>Random text before the div containing the conll tag</p>
|
| 89 |
+
<div class="panel-body">
|
| 90 |
+
|
| 91 |
+
<conll>
|
| 92 |
+
|
| 93 |
+
# sent_id = KAD_15_Money-Wahala_MG__22
|
| 94 |
+
# sound_url = http://www.tal.univ-paris3.fr/trameur/iTrameur-naija/mp3/KAD_15_Money-Wahala_MG.mp3
|
| 95 |
+
# speaker_id = Sp194
|
| 96 |
+
# text = # how { di gene- || generation } go be ?//
|
| 97 |
+
# text_en = How will the next gene… generation be?
|
| 98 |
+
# text_ortho = How di gene-... generation go be?
|
| 99 |
+
# shownfeatures = FORM, UPOS, LEMMA, MISC.Gloss, FEATS.PronType, FEATS.Aspect
|
| 100 |
+
1 # # PUNCT _ _ 2 punct _ AlignBegin=85160|AlignEnd=85800|Gloss=PUNCT
|
| 101 |
+
2 how how ADV _ PronType=Int 0 root 10:@mod AlignBegin=85800|AlignEnd=86049|Gloss=how.Q
|
| 102 |
+
3 { { PUNCT _ _ 5 punct _ AlignBegin=86049|AlignEnd=86079|Gloss=PUNCT
|
| 103 |
+
4 di the DET _ Definite=Def|PronType=Art 5 det _ AlignBegin=86079|AlignEnd=86230|Gloss=DEF.ART
|
| 104 |
+
5 gene- X X _ _ 9 subj _ AlignBegin=86230|AlignEnd=86530|Gloss=X
|
| 105 |
+
6 || || PUNCT _ _ 7 punct _ AlignBegin=86530|AlignEnd=86560|Gloss=PUNCT
|
| 106 |
+
7 generation generation NOUN _ _ 5 conj:coord _ AlignBegin=86560|AlignEnd=86950|Gloss=generation
|
| 107 |
+
8 } } PUNCT _ _ 5 punct _ AlignBegin=86950|AlignEnd=86980|Gloss=PUNCT
|
| 108 |
+
9 go go AUX _ Aspect=Prosp 2 comp:cleft _ AlignBegin=86980|AlignEnd=87110|Gloss=PROSP
|
| 109 |
+
10 be be VERB _ PartType=Cop 9 comp:aux _ AlignBegin=87110|AlignEnd=87310|Gloss=be
|
| 110 |
+
11 ?// ?// PUNCT _ _ 2 punct _ AlignBegin=87310|AlignEnd=87340|Gloss=PUNCT
|
| 111 |
+
|
| 112 |
+
1 l' le DET _ _ 2 spe _ _
|
| 113 |
+
2 avenir avenir NOM _ _ 3 subj _ _
|
| 114 |
+
3 dépend dépendre VRB _ _ 0 root _ _
|
| 115 |
+
4 de de PRE _ _ 3 comp _ _
|
| 116 |
+
5 notre son DET _ _ 6 spe _ _
|
| 117 |
+
6 capacité capacité NOM _ _ 4 dep _ _
|
| 118 |
+
7 à à PRE _ _ 6 dep _ _
|
| 119 |
+
8 construire construire VNF _ _ 7 dep _ _
|
| 120 |
+
9 à à PRE _ _ 7 para _ _
|
| 121 |
+
10 créer créer VNF _ _ 9 dep _ _
|
| 122 |
+
11 à à PRE _ _ 9 para _ _
|
| 123 |
+
12 rêver rêver VNF _ _ 11 dep _ _
|
| 124 |
+
13 ensemble ensemble ADV _ _ 12 ad _ _
|
| 125 |
+
14 les le DET _ _ 15 spe _ _
|
| 126 |
+
15 voies voie NOM _ _ 12 comp _ _
|
| 127 |
+
16 de de PRE _ _ 15 dep _ _
|
| 128 |
+
17 l' le DET _ _ 18 spe _ _
|
| 129 |
+
18 aventure aventure NOM _ _ 16 dep _ _
|
| 130 |
+
19 humaine humain ADJ _ _ 18 dep _ _
|
| 131 |
+
</conll>
|
| 132 |
+
|
| 133 |
+
</div>
|
| 134 |
+
<p>Random text after the div containing the conll tag</p>
|
| 135 |
+
</div>
|
| 136 |
+
</div>
|
| 137 |
+
|
| 138 |
+
<div class="row">
|
| 139 |
+
<div class="panel panel-danger">
|
| 140 |
+
<div class="panel-heading" style="background-color: #dd137b;color:white; border-color: #dd137b;"><h2>Another example of CoNLL-U data surrounded by Conll tags</h2></div>
|
| 141 |
+
<div class="panel-body">
|
| 142 |
+
<conll>
|
| 143 |
+
|
| 144 |
+
# text_en = I wrote the letter with a quill.
|
| 145 |
+
1 Я ja PRON _ Case=Nom|Number=Sing|Person=1|PronType=Prs 2 nsubj _ Gloss=I
|
| 146 |
+
2 написал napisat' VERB _ Gender=Masc|Number=Sing|VerbForm=Part|Voice=Act 0 root _ Gloss=wrote
|
| 147 |
+
3 письмо pis'mo NOUN _ Case=Acc|Gender=Neut|Number=Sing 2 dobj _ Gloss=the-letter
|
| 148 |
+
4 пером pero NOUN _ Case=Ins|Gender=Neut|Number=Sing 2 nmod _ Gloss=with-a-quill
|
| 149 |
+
|
| 150 |
+
1 car car COO _ _ 12 mark _ _
|
| 151 |
+
2 dans dans PRE _ _ 12 periph _ _
|
| 152 |
+
3 un un DET _ _ 4 spe _ _
|
| 153 |
+
4 monde monde NOM _ _ 2 dep _ _
|
| 154 |
+
5 où où PRQ _ _ 9 ad _ _
|
| 155 |
+
6 rien rien PRO _ _ 8 subj _ _
|
| 156 |
+
7 n' ne CLN _ _ 8 ad _ _
|
| 157 |
+
8 est être VRB _ _ 4 dep _ _
|
| 158 |
+
9 figé figer VPP _ _ 8 aux _ _
|
| 159 |
+
10 l' le DET _ _ 11 spe _ _
|
| 160 |
+
11 avenir avenir NOM _ _ 12 subj _ _
|
| 161 |
+
12 dépend dépendre VRB _ _ 0 root _ _
|
| 162 |
+
13 de de PRE _ _ 12 comp _ _
|
| 163 |
+
14 nous lui PRO _ _ 13 dep _ _
|
| 164 |
+
</conll>
|
| 165 |
+
</div>
|
| 166 |
+
</div>
|
| 167 |
+
</div>
|
| 168 |
+
</div>
|
| 169 |
+
|
| 170 |
+
<!--
|
| 171 |
+
|
| 172 |
+
|
| 173 |
+
-->
|
| 174 |
+
|
| 175 |
+
<!-- <script language="JavaScript" type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.js"></script> -->
|
| 176 |
+
<script src="d3.js"></script>
|
| 177 |
+
<!-- <script src="d3-drag.min.js"></script> -->
|
| 178 |
+
<!-- <script src="https://code.jquery.com/jquery-3.2.1.min.js"
|
| 179 |
+
integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4="
|
| 180 |
+
crossorigin="anonymous"></script> -->
|
| 181 |
+
<script src="jquery-3.2.1.min.js"></script>
|
| 182 |
+
<!-- <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script> -->
|
| 183 |
+
<!-- <script src="bootstrap.min.css"></script> -->
|
| 184 |
+
<script src="FileSaver.min.js"></script>
|
| 185 |
+
<script src="jszip.min.js"></script>
|
| 186 |
+
<!-- <script type="text/javascript" src="rgbcolor.js"></script>
|
| 187 |
+
<script type="text/javascript" src="StackBlur.js"></script> -->
|
| 188 |
+
<script type="text/javascript" src="canvg.js"></script>
|
| 189 |
+
<script language="JavaScript" type="text/javascript" src="arborator-draft.js"></script>
|
| 190 |
+
<script>
|
| 191 |
+
|
| 192 |
+
window.onload = function () {
|
| 193 |
+
new ArboratorDraft(myshownfeatures=["FORM", "UPOS", "LEMMA", "MISC.Gloss"]); // START. myshownfeatures has the standard value here and can be omitted if this is the desired set of features to be shown.
|
| 194 |
+
}
|
| 195 |
+
</script>
|
| 196 |
+
</body>
|
| 197 |
+
|
| 198 |
+
</html>
|
src/arborator-draft/jquery-3.2.1.min.js
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*! jQuery v3.2.1 | (c) JS Foundation and other contributors | jquery.org/license */
|
| 2 |
+
!function(a,b){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){"use strict";var c=[],d=a.document,e=Object.getPrototypeOf,f=c.slice,g=c.concat,h=c.push,i=c.indexOf,j={},k=j.toString,l=j.hasOwnProperty,m=l.toString,n=m.call(Object),o={};function p(a,b){b=b||d;var c=b.createElement("script");c.text=a,b.head.appendChild(c).parentNode.removeChild(c)}var q="3.2.1",r=function(a,b){return new r.fn.init(a,b)},s=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,t=/^-ms-/,u=/-([a-z])/g,v=function(a,b){return b.toUpperCase()};r.fn=r.prototype={jquery:q,constructor:r,length:0,toArray:function(){return f.call(this)},get:function(a){return null==a?f.call(this):a<0?this[a+this.length]:this[a]},pushStack:function(a){var b=r.merge(this.constructor(),a);return b.prevObject=this,b},each:function(a){return r.each(this,a)},map:function(a){return this.pushStack(r.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(f.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(a<0?b:0);return this.pushStack(c>=0&&c<b?[this[c]]:[])},end:function(){return this.prevObject||this.constructor()},push:h,sort:c.sort,splice:c.splice},r.extend=r.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||r.isFunction(g)||(g={}),h===i&&(g=this,h--);h<i;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(r.isPlainObject(d)||(e=Array.isArray(d)))?(e?(e=!1,f=c&&Array.isArray(c)?c:[]):f=c&&r.isPlainObject(c)?c:{},g[b]=r.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},r.extend({expando:"jQuery"+(q+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===r.type(a)},isWindow:function(a){return null!=a&&a===a.window},isNumeric:function(a){var b=r.type(a);return("number"===b||"string"===b)&&!isNaN(a-parseFloat(a))},isPlainObject:function(a){var b,c;return!(!a||"[object Object]"!==k.call(a))&&(!(b=e(a))||(c=l.call(b,"constructor")&&b.constructor,"function"==typeof c&&m.call(c)===n))},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?j[k.call(a)]||"object":typeof a},globalEval:function(a){p(a)},camelCase:function(a){return a.replace(t,"ms-").replace(u,v)},each:function(a,b){var c,d=0;if(w(a)){for(c=a.length;d<c;d++)if(b.call(a[d],d,a[d])===!1)break}else for(d in a)if(b.call(a[d],d,a[d])===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(s,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(w(Object(a))?r.merge(c,"string"==typeof a?[a]:a):h.call(c,a)),c},inArray:function(a,b,c){return null==b?-1:i.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;d<c;d++)a[e++]=b[d];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;f<g;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,e,f=0,h=[];if(w(a))for(d=a.length;f<d;f++)e=b(a[f],f,c),null!=e&&h.push(e);else for(f in a)e=b(a[f],f,c),null!=e&&h.push(e);return g.apply([],h)},guid:1,proxy:function(a,b){var c,d,e;if("string"==typeof b&&(c=a[b],b=a,a=c),r.isFunction(a))return d=f.call(arguments,2),e=function(){return a.apply(b||this,d.concat(f.call(arguments)))},e.guid=a.guid=a.guid||r.guid++,e},now:Date.now,support:o}),"function"==typeof Symbol&&(r.fn[Symbol.iterator]=c[Symbol.iterator]),r.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(a,b){j["[object "+b+"]"]=b.toLowerCase()});function w(a){var b=!!a&&"length"in a&&a.length,c=r.type(a);return"function"!==c&&!r.isWindow(a)&&("array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a)}var x=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ha(),z=ha(),A=ha(),B=function(a,b){return a===b&&(l=!0),0},C={}.hasOwnProperty,D=[],E=D.pop,F=D.push,G=D.push,H=D.slice,I=function(a,b){for(var c=0,d=a.length;c<d;c++)if(a[c]===b)return c;return-1},J="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",K="[\\x20\\t\\r\\n\\f]",L="(?:\\\\.|[\\w-]|[^\0-\\xa0])+",M="\\["+K+"*("+L+")(?:"+K+"*([*^$|!~]?=)"+K+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+L+"))|)"+K+"*\\]",N=":("+L+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+M+")*)|.*)\\)|)",O=new RegExp(K+"+","g"),P=new RegExp("^"+K+"+|((?:^|[^\\\\])(?:\\\\.)*)"+K+"+$","g"),Q=new RegExp("^"+K+"*,"+K+"*"),R=new RegExp("^"+K+"*([>+~]|"+K+")"+K+"*"),S=new RegExp("="+K+"*([^\\]'\"]*?)"+K+"*\\]","g"),T=new RegExp(N),U=new RegExp("^"+L+"$"),V={ID:new RegExp("^#("+L+")"),CLASS:new RegExp("^\\.("+L+")"),TAG:new RegExp("^("+L+"|[*])"),ATTR:new RegExp("^"+M),PSEUDO:new RegExp("^"+N),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+K+"*(even|odd|(([+-]|)(\\d*)n|)"+K+"*(?:([+-]|)"+K+"*(\\d+)|))"+K+"*\\)|)","i"),bool:new RegExp("^(?:"+J+")$","i"),needsContext:new RegExp("^"+K+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+K+"*((?:-\\d)?\\d*)"+K+"*\\)|)(?=[^-]|$)","i")},W=/^(?:input|select|textarea|button)$/i,X=/^h\d$/i,Y=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,$=/[+~]/,_=new RegExp("\\\\([\\da-f]{1,6}"+K+"?|("+K+")|.)","ig"),aa=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:d<0?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},ba=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ca=function(a,b){return b?"\0"===a?"\ufffd":a.slice(0,-1)+"\\"+a.charCodeAt(a.length-1).toString(16)+" ":"\\"+a},da=function(){m()},ea=ta(function(a){return a.disabled===!0&&("form"in a||"label"in a)},{dir:"parentNode",next:"legend"});try{G.apply(D=H.call(v.childNodes),v.childNodes),D[v.childNodes.length].nodeType}catch(fa){G={apply:D.length?function(a,b){F.apply(a,H.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function ga(a,b,d,e){var f,h,j,k,l,o,r,s=b&&b.ownerDocument,w=b?b.nodeType:9;if(d=d||[],"string"!=typeof a||!a||1!==w&&9!==w&&11!==w)return d;if(!e&&((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,p)){if(11!==w&&(l=Z.exec(a)))if(f=l[1]){if(9===w){if(!(j=b.getElementById(f)))return d;if(j.id===f)return d.push(j),d}else if(s&&(j=s.getElementById(f))&&t(b,j)&&j.id===f)return d.push(j),d}else{if(l[2])return G.apply(d,b.getElementsByTagName(a)),d;if((f=l[3])&&c.getElementsByClassName&&b.getElementsByClassName)return G.apply(d,b.getElementsByClassName(f)),d}if(c.qsa&&!A[a+" "]&&(!q||!q.test(a))){if(1!==w)s=b,r=a;else if("object"!==b.nodeName.toLowerCase()){(k=b.getAttribute("id"))?k=k.replace(ba,ca):b.setAttribute("id",k=u),o=g(a),h=o.length;while(h--)o[h]="#"+k+" "+sa(o[h]);r=o.join(","),s=$.test(a)&&qa(b.parentNode)||b}if(r)try{return G.apply(d,s.querySelectorAll(r)),d}catch(x){}finally{k===u&&b.removeAttribute("id")}}}return i(a.replace(P,"$1"),b,d,e)}function ha(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ia(a){return a[u]=!0,a}function ja(a){var b=n.createElement("fieldset");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ka(a,b){var c=a.split("|"),e=c.length;while(e--)d.attrHandle[c[e]]=b}function la(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&a.sourceIndex-b.sourceIndex;if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function na(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function oa(a){return function(b){return"form"in b?b.parentNode&&b.disabled===!1?"label"in b?"label"in b.parentNode?b.parentNode.disabled===a:b.disabled===a:b.isDisabled===a||b.isDisabled!==!a&&ea(b)===a:b.disabled===a:"label"in b&&b.disabled===a}}function pa(a){return ia(function(b){return b=+b,ia(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function qa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=ga.support={},f=ga.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return!!b&&"HTML"!==b.nodeName},m=ga.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=n.documentElement,p=!f(n),v!==n&&(e=n.defaultView)&&e.top!==e&&(e.addEventListener?e.addEventListener("unload",da,!1):e.attachEvent&&e.attachEvent("onunload",da)),c.attributes=ja(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ja(function(a){return a.appendChild(n.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Y.test(n.getElementsByClassName),c.getById=ja(function(a){return o.appendChild(a).id=u,!n.getElementsByName||!n.getElementsByName(u).length}),c.getById?(d.filter.ID=function(a){var b=a.replace(_,aa);return function(a){return a.getAttribute("id")===b}},d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c?[c]:[]}}):(d.filter.ID=function(a){var b=a.replace(_,aa);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}},d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c,d,e,f=b.getElementById(a);if(f){if(c=f.getAttributeNode("id"),c&&c.value===a)return[f];e=b.getElementsByName(a),d=0;while(f=e[d++])if(c=f.getAttributeNode("id"),c&&c.value===a)return[f]}return[]}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){if("undefined"!=typeof b.getElementsByClassName&&p)return b.getElementsByClassName(a)},r=[],q=[],(c.qsa=Y.test(n.querySelectorAll))&&(ja(function(a){o.appendChild(a).innerHTML="<a id='"+u+"'></a><select id='"+u+"-\r\\' msallowcapture=''><option selected=''></option></select>",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+K+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+K+"*(?:value|"+J+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ja(function(a){a.innerHTML="<a href='' disabled='disabled'></a><select disabled='disabled'><option/></select>";var b=n.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+K+"*[*^$|!~]?="),2!==a.querySelectorAll(":enabled").length&&q.push(":enabled",":disabled"),o.appendChild(a).disabled=!0,2!==a.querySelectorAll(":disabled").length&&q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=Y.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ja(function(a){c.disconnectedMatch=s.call(a,"*"),s.call(a,"[s!='']:x"),r.push("!=",N)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=Y.test(o.compareDocumentPosition),t=b||Y.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===n||a.ownerDocument===v&&t(v,a)?-1:b===n||b.ownerDocument===v&&t(v,b)?1:k?I(k,a)-I(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,g=[a],h=[b];if(!e||!f)return a===n?-1:b===n?1:e?-1:f?1:k?I(k,a)-I(k,b):0;if(e===f)return la(a,b);c=a;while(c=c.parentNode)g.unshift(c);c=b;while(c=c.parentNode)h.unshift(c);while(g[d]===h[d])d++;return d?la(g[d],h[d]):g[d]===v?-1:h[d]===v?1:0},n):n},ga.matches=function(a,b){return ga(a,null,null,b)},ga.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(S,"='$1']"),c.matchesSelector&&p&&!A[b+" "]&&(!r||!r.test(b))&&(!q||!q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return ga(b,n,null,[a]).length>0},ga.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},ga.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&C.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},ga.escape=function(a){return(a+"").replace(ba,ca)},ga.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},ga.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=ga.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=ga.selectors={cacheLength:50,createPseudo:ia,match:V,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(_,aa),a[3]=(a[3]||a[4]||a[5]||"").replace(_,aa),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||ga.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&ga.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return V.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&T.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(_,aa).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+K+")"+a+"("+K+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=ga.attr(d,a);return null==e?"!="===b:!b||(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(O," ")+" ").indexOf(c)>-1:"|="===b&&(e===c||e.slice(0,c.length+1)===c+"-"))}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h,t=!1;if(q){if(f){while(p){m=b;while(m=m[p])if(h?m.nodeName.toLowerCase()===r:1===m.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){m=q,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n&&j[2],m=n&&q.childNodes[n];while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if(1===m.nodeType&&++t&&m===b){k[a]=[w,n,t];break}}else if(s&&(m=b,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n),t===!1)while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if((h?m.nodeName.toLowerCase()===r:1===m.nodeType)&&++t&&(s&&(l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),k[a]=[w,t]),m===b))break;return t-=e,t===d||t%d===0&&t/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||ga.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ia(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=I(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ia(function(a){var b=[],c=[],d=h(a.replace(P,"$1"));return d[u]?ia(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ia(function(a){return function(b){return ga(a,b).length>0}}),contains:ia(function(a){return a=a.replace(_,aa),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ia(function(a){return U.test(a||"")||ga.error("unsupported lang: "+a),a=a.replace(_,aa).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:oa(!1),disabled:oa(!0),checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return X.test(a.nodeName)},input:function(a){return W.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:pa(function(){return[0]}),last:pa(function(a,b){return[b-1]}),eq:pa(function(a,b,c){return[c<0?c+b:c]}),even:pa(function(a,b){for(var c=0;c<b;c+=2)a.push(c);return a}),odd:pa(function(a,b){for(var c=1;c<b;c+=2)a.push(c);return a}),lt:pa(function(a,b,c){for(var d=c<0?c+b:c;--d>=0;)a.push(d);return a}),gt:pa(function(a,b,c){for(var d=c<0?c+b:c;++d<b;)a.push(d);return a})}},d.pseudos.nth=d.pseudos.eq;for(b in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})d.pseudos[b]=ma(b);for(b in{submit:!0,reset:!0})d.pseudos[b]=na(b);function ra(){}ra.prototype=d.filters=d.pseudos,d.setFilters=new ra,g=ga.tokenize=function(a,b){var c,e,f,g,h,i,j,k=z[a+" "];if(k)return b?0:k.slice(0);h=a,i=[],j=d.preFilter;while(h){c&&!(e=Q.exec(h))||(e&&(h=h.slice(e[0].length)||h),i.push(f=[])),c=!1,(e=R.exec(h))&&(c=e.shift(),f.push({value:c,type:e[0].replace(P," ")}),h=h.slice(c.length));for(g in d.filter)!(e=V[g].exec(h))||j[g]&&!(e=j[g](e))||(c=e.shift(),f.push({value:c,type:g,matches:e}),h=h.slice(c.length));if(!c)break}return b?h.length:h?ga.error(a):z(a,i).slice(0)};function sa(a){for(var b=0,c=a.length,d="";b<c;b++)d+=a[b].value;return d}function ta(a,b,c){var d=b.dir,e=b.next,f=e||d,g=c&&"parentNode"===f,h=x++;return b.first?function(b,c,e){while(b=b[d])if(1===b.nodeType||g)return a(b,c,e);return!1}:function(b,c,i){var j,k,l,m=[w,h];if(i){while(b=b[d])if((1===b.nodeType||g)&&a(b,c,i))return!0}else while(b=b[d])if(1===b.nodeType||g)if(l=b[u]||(b[u]={}),k=l[b.uniqueID]||(l[b.uniqueID]={}),e&&e===b.nodeName.toLowerCase())b=b[d]||b;else{if((j=k[f])&&j[0]===w&&j[1]===h)return m[2]=j[2];if(k[f]=m,m[2]=a(b,c,i))return!0}return!1}}function ua(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function va(a,b,c){for(var d=0,e=b.length;d<e;d++)ga(a,b[d],c);return c}function wa(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;h<i;h++)(f=a[h])&&(c&&!c(f,d,e)||(g.push(f),j&&b.push(h)));return g}function xa(a,b,c,d,e,f){return d&&!d[u]&&(d=xa(d)),e&&!e[u]&&(e=xa(e,f)),ia(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||va(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:wa(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=wa(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?I(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=wa(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):G.apply(g,r)})}function ya(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=ta(function(a){return a===b},h,!0),l=ta(function(a){return I(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];i<f;i++)if(c=d.relative[a[i].type])m=[ta(ua(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;e<f;e++)if(d.relative[a[e].type])break;return xa(i>1&&ua(m),i>1&&sa(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(P,"$1"),c,i<e&&ya(a.slice(i,e)),e<f&&ya(a=a.slice(e)),e<f&&sa(a))}m.push(c)}return ua(m)}function za(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,o,q,r=0,s="0",t=f&&[],u=[],v=j,x=f||e&&d.find.TAG("*",k),y=w+=null==v?1:Math.random()||.1,z=x.length;for(k&&(j=g===n||g||k);s!==z&&null!=(l=x[s]);s++){if(e&&l){o=0,g||l.ownerDocument===n||(m(l),h=!p);while(q=a[o++])if(q(l,g||n,h)){i.push(l);break}k&&(w=y)}c&&((l=!q&&l)&&r--,f&&t.push(l))}if(r+=s,c&&s!==r){o=0;while(q=b[o++])q(t,u,g,h);if(f){if(r>0)while(s--)t[s]||u[s]||(u[s]=E.call(i));u=wa(u)}G.apply(i,u),k&&!f&&u.length>0&&r+b.length>1&&ga.uniqueSort(i)}return k&&(w=y,j=v),t};return c?ia(f):f}return h=ga.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=ya(b[c]),f[u]?d.push(f):e.push(f);f=A(a,za(e,d)),f.selector=a}return f},i=ga.select=function(a,b,c,e){var f,i,j,k,l,m="function"==typeof a&&a,n=!e&&g(a=m.selector||a);if(c=c||[],1===n.length){if(i=n[0]=n[0].slice(0),i.length>2&&"ID"===(j=i[0]).type&&9===b.nodeType&&p&&d.relative[i[1].type]){if(b=(d.find.ID(j.matches[0].replace(_,aa),b)||[])[0],!b)return c;m&&(b=b.parentNode),a=a.slice(i.shift().value.length)}f=V.needsContext.test(a)?0:i.length;while(f--){if(j=i[f],d.relative[k=j.type])break;if((l=d.find[k])&&(e=l(j.matches[0].replace(_,aa),$.test(i[0].type)&&qa(b.parentNode)||b))){if(i.splice(f,1),a=e.length&&sa(i),!a)return G.apply(c,e),c;break}}}return(m||h(a,n))(e,b,!p,c,!b||$.test(a)&&qa(b.parentNode)||b),c},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ja(function(a){return 1&a.compareDocumentPosition(n.createElement("fieldset"))}),ja(function(a){return a.innerHTML="<a href='#'></a>","#"===a.firstChild.getAttribute("href")})||ka("type|href|height|width",function(a,b,c){if(!c)return a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ja(function(a){return a.innerHTML="<input/>",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ka("value",function(a,b,c){if(!c&&"input"===a.nodeName.toLowerCase())return a.defaultValue}),ja(function(a){return null==a.getAttribute("disabled")})||ka(J,function(a,b,c){var d;if(!c)return a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),ga}(a);r.find=x,r.expr=x.selectors,r.expr[":"]=r.expr.pseudos,r.uniqueSort=r.unique=x.uniqueSort,r.text=x.getText,r.isXMLDoc=x.isXML,r.contains=x.contains,r.escapeSelector=x.escape;var y=function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&r(a).is(c))break;d.push(a)}return d},z=function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c},A=r.expr.match.needsContext;function B(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()}var C=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i,D=/^.[^:#\[\.,]*$/;function E(a,b,c){return r.isFunction(b)?r.grep(a,function(a,d){return!!b.call(a,d,a)!==c}):b.nodeType?r.grep(a,function(a){return a===b!==c}):"string"!=typeof b?r.grep(a,function(a){return i.call(b,a)>-1!==c}):D.test(b)?r.filter(b,a,c):(b=r.filter(b,a),r.grep(a,function(a){return i.call(b,a)>-1!==c&&1===a.nodeType}))}r.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?r.find.matchesSelector(d,a)?[d]:[]:r.find.matches(a,r.grep(b,function(a){return 1===a.nodeType}))},r.fn.extend({find:function(a){var b,c,d=this.length,e=this;if("string"!=typeof a)return this.pushStack(r(a).filter(function(){for(b=0;b<d;b++)if(r.contains(e[b],this))return!0}));for(c=this.pushStack([]),b=0;b<d;b++)r.find(a,e[b],c);return d>1?r.uniqueSort(c):c},filter:function(a){return this.pushStack(E(this,a||[],!1))},not:function(a){return this.pushStack(E(this,a||[],!0))},is:function(a){return!!E(this,"string"==typeof a&&A.test(a)?r(a):a||[],!1).length}});var F,G=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/,H=r.fn.init=function(a,b,c){var e,f;if(!a)return this;if(c=c||F,"string"==typeof a){if(e="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:G.exec(a),!e||!e[1]&&b)return!b||b.jquery?(b||c).find(a):this.constructor(b).find(a);if(e[1]){if(b=b instanceof r?b[0]:b,r.merge(this,r.parseHTML(e[1],b&&b.nodeType?b.ownerDocument||b:d,!0)),C.test(e[1])&&r.isPlainObject(b))for(e in b)r.isFunction(this[e])?this[e](b[e]):this.attr(e,b[e]);return this}return f=d.getElementById(e[2]),f&&(this[0]=f,this.length=1),this}return a.nodeType?(this[0]=a,this.length=1,this):r.isFunction(a)?void 0!==c.ready?c.ready(a):a(r):r.makeArray(a,this)};H.prototype=r.fn,F=r(d);var I=/^(?:parents|prev(?:Until|All))/,J={children:!0,contents:!0,next:!0,prev:!0};r.fn.extend({has:function(a){var b=r(a,this),c=b.length;return this.filter(function(){for(var a=0;a<c;a++)if(r.contains(this,b[a]))return!0})},closest:function(a,b){var c,d=0,e=this.length,f=[],g="string"!=typeof a&&r(a);if(!A.test(a))for(;d<e;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&r.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?r.uniqueSort(f):f)},index:function(a){return a?"string"==typeof a?i.call(r(a),this[0]):i.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(r.uniqueSort(r.merge(this.get(),r(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function K(a,b){while((a=a[b])&&1!==a.nodeType);return a}r.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return y(a,"parentNode")},parentsUntil:function(a,b,c){return y(a,"parentNode",c)},next:function(a){return K(a,"nextSibling")},prev:function(a){return K(a,"previousSibling")},nextAll:function(a){return y(a,"nextSibling")},prevAll:function(a){return y(a,"previousSibling")},nextUntil:function(a,b,c){return y(a,"nextSibling",c)},prevUntil:function(a,b,c){return y(a,"previousSibling",c)},siblings:function(a){return z((a.parentNode||{}).firstChild,a)},children:function(a){return z(a.firstChild)},contents:function(a){return B(a,"iframe")?a.contentDocument:(B(a,"template")&&(a=a.content||a),r.merge([],a.childNodes))}},function(a,b){r.fn[a]=function(c,d){var e=r.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=r.filter(d,e)),this.length>1&&(J[a]||r.uniqueSort(e),I.test(a)&&e.reverse()),this.pushStack(e)}});var L=/[^\x20\t\r\n\f]+/g;function M(a){var b={};return r.each(a.match(L)||[],function(a,c){b[c]=!0}),b}r.Callbacks=function(a){a="string"==typeof a?M(a):r.extend({},a);var b,c,d,e,f=[],g=[],h=-1,i=function(){for(e=e||a.once,d=b=!0;g.length;h=-1){c=g.shift();while(++h<f.length)f[h].apply(c[0],c[1])===!1&&a.stopOnFalse&&(h=f.length,c=!1)}a.memory||(c=!1),b=!1,e&&(f=c?[]:"")},j={add:function(){return f&&(c&&!b&&(h=f.length-1,g.push(c)),function d(b){r.each(b,function(b,c){r.isFunction(c)?a.unique&&j.has(c)||f.push(c):c&&c.length&&"string"!==r.type(c)&&d(c)})}(arguments),c&&!b&&i()),this},remove:function(){return r.each(arguments,function(a,b){var c;while((c=r.inArray(b,f,c))>-1)f.splice(c,1),c<=h&&h--}),this},has:function(a){return a?r.inArray(a,f)>-1:f.length>0},empty:function(){return f&&(f=[]),this},disable:function(){return e=g=[],f=c="",this},disabled:function(){return!f},lock:function(){return e=g=[],c||b||(f=c=""),this},locked:function(){return!!e},fireWith:function(a,c){return e||(c=c||[],c=[a,c.slice?c.slice():c],g.push(c),b||i()),this},fire:function(){return j.fireWith(this,arguments),this},fired:function(){return!!d}};return j};function N(a){return a}function O(a){throw a}function P(a,b,c,d){var e;try{a&&r.isFunction(e=a.promise)?e.call(a).done(b).fail(c):a&&r.isFunction(e=a.then)?e.call(a,b,c):b.apply(void 0,[a].slice(d))}catch(a){c.apply(void 0,[a])}}r.extend({Deferred:function(b){var c=[["notify","progress",r.Callbacks("memory"),r.Callbacks("memory"),2],["resolve","done",r.Callbacks("once memory"),r.Callbacks("once memory"),0,"resolved"],["reject","fail",r.Callbacks("once memory"),r.Callbacks("once memory"),1,"rejected"]],d="pending",e={state:function(){return d},always:function(){return f.done(arguments).fail(arguments),this},"catch":function(a){return e.then(null,a)},pipe:function(){var a=arguments;return r.Deferred(function(b){r.each(c,function(c,d){var e=r.isFunction(a[d[4]])&&a[d[4]];f[d[1]](function(){var a=e&&e.apply(this,arguments);a&&r.isFunction(a.promise)?a.promise().progress(b.notify).done(b.resolve).fail(b.reject):b[d[0]+"With"](this,e?[a]:arguments)})}),a=null}).promise()},then:function(b,d,e){var f=0;function g(b,c,d,e){return function(){var h=this,i=arguments,j=function(){var a,j;if(!(b<f)){if(a=d.apply(h,i),a===c.promise())throw new TypeError("Thenable self-resolution");j=a&&("object"==typeof a||"function"==typeof a)&&a.then,r.isFunction(j)?e?j.call(a,g(f,c,N,e),g(f,c,O,e)):(f++,j.call(a,g(f,c,N,e),g(f,c,O,e),g(f,c,N,c.notifyWith))):(d!==N&&(h=void 0,i=[a]),(e||c.resolveWith)(h,i))}},k=e?j:function(){try{j()}catch(a){r.Deferred.exceptionHook&&r.Deferred.exceptionHook(a,k.stackTrace),b+1>=f&&(d!==O&&(h=void 0,i=[a]),c.rejectWith(h,i))}};b?k():(r.Deferred.getStackHook&&(k.stackTrace=r.Deferred.getStackHook()),a.setTimeout(k))}}return r.Deferred(function(a){c[0][3].add(g(0,a,r.isFunction(e)?e:N,a.notifyWith)),c[1][3].add(g(0,a,r.isFunction(b)?b:N)),c[2][3].add(g(0,a,r.isFunction(d)?d:O))}).promise()},promise:function(a){return null!=a?r.extend(a,e):e}},f={};return r.each(c,function(a,b){var g=b[2],h=b[5];e[b[1]]=g.add,h&&g.add(function(){d=h},c[3-a][2].disable,c[0][2].lock),g.add(b[3].fire),f[b[0]]=function(){return f[b[0]+"With"](this===f?void 0:this,arguments),this},f[b[0]+"With"]=g.fireWith}),e.promise(f),b&&b.call(f,f),f},when:function(a){var b=arguments.length,c=b,d=Array(c),e=f.call(arguments),g=r.Deferred(),h=function(a){return function(c){d[a]=this,e[a]=arguments.length>1?f.call(arguments):c,--b||g.resolveWith(d,e)}};if(b<=1&&(P(a,g.done(h(c)).resolve,g.reject,!b),"pending"===g.state()||r.isFunction(e[c]&&e[c].then)))return g.then();while(c--)P(e[c],h(c),g.reject);return g.promise()}});var Q=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;r.Deferred.exceptionHook=function(b,c){a.console&&a.console.warn&&b&&Q.test(b.name)&&a.console.warn("jQuery.Deferred exception: "+b.message,b.stack,c)},r.readyException=function(b){a.setTimeout(function(){throw b})};var R=r.Deferred();r.fn.ready=function(a){return R.then(a)["catch"](function(a){r.readyException(a)}),this},r.extend({isReady:!1,readyWait:1,ready:function(a){(a===!0?--r.readyWait:r.isReady)||(r.isReady=!0,a!==!0&&--r.readyWait>0||R.resolveWith(d,[r]))}}),r.ready.then=R.then;function S(){d.removeEventListener("DOMContentLoaded",S),
|
| 3 |
+
a.removeEventListener("load",S),r.ready()}"complete"===d.readyState||"loading"!==d.readyState&&!d.documentElement.doScroll?a.setTimeout(r.ready):(d.addEventListener("DOMContentLoaded",S),a.addEventListener("load",S));var T=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===r.type(c)){e=!0;for(h in c)T(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,r.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(r(a),c)})),b))for(;h<i;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},U=function(a){return 1===a.nodeType||9===a.nodeType||!+a.nodeType};function V(){this.expando=r.expando+V.uid++}V.uid=1,V.prototype={cache:function(a){var b=a[this.expando];return b||(b={},U(a)&&(a.nodeType?a[this.expando]=b:Object.defineProperty(a,this.expando,{value:b,configurable:!0}))),b},set:function(a,b,c){var d,e=this.cache(a);if("string"==typeof b)e[r.camelCase(b)]=c;else for(d in b)e[r.camelCase(d)]=b[d];return e},get:function(a,b){return void 0===b?this.cache(a):a[this.expando]&&a[this.expando][r.camelCase(b)]},access:function(a,b,c){return void 0===b||b&&"string"==typeof b&&void 0===c?this.get(a,b):(this.set(a,b,c),void 0!==c?c:b)},remove:function(a,b){var c,d=a[this.expando];if(void 0!==d){if(void 0!==b){Array.isArray(b)?b=b.map(r.camelCase):(b=r.camelCase(b),b=b in d?[b]:b.match(L)||[]),c=b.length;while(c--)delete d[b[c]]}(void 0===b||r.isEmptyObject(d))&&(a.nodeType?a[this.expando]=void 0:delete a[this.expando])}},hasData:function(a){var b=a[this.expando];return void 0!==b&&!r.isEmptyObject(b)}};var W=new V,X=new V,Y=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,Z=/[A-Z]/g;function $(a){return"true"===a||"false"!==a&&("null"===a?null:a===+a+""?+a:Y.test(a)?JSON.parse(a):a)}function _(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(Z,"-$&").toLowerCase(),c=a.getAttribute(d),"string"==typeof c){try{c=$(c)}catch(e){}X.set(a,b,c)}else c=void 0;return c}r.extend({hasData:function(a){return X.hasData(a)||W.hasData(a)},data:function(a,b,c){return X.access(a,b,c)},removeData:function(a,b){X.remove(a,b)},_data:function(a,b,c){return W.access(a,b,c)},_removeData:function(a,b){W.remove(a,b)}}),r.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=X.get(f),1===f.nodeType&&!W.get(f,"hasDataAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=r.camelCase(d.slice(5)),_(f,d,e[d])));W.set(f,"hasDataAttrs",!0)}return e}return"object"==typeof a?this.each(function(){X.set(this,a)}):T(this,function(b){var c;if(f&&void 0===b){if(c=X.get(f,a),void 0!==c)return c;if(c=_(f,a),void 0!==c)return c}else this.each(function(){X.set(this,a,b)})},null,b,arguments.length>1,null,!0)},removeData:function(a){return this.each(function(){X.remove(this,a)})}}),r.extend({queue:function(a,b,c){var d;if(a)return b=(b||"fx")+"queue",d=W.get(a,b),c&&(!d||Array.isArray(c)?d=W.access(a,b,r.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||"fx";var c=r.queue(a,b),d=c.length,e=c.shift(),f=r._queueHooks(a,b),g=function(){r.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return W.get(a,c)||W.access(a,c,{empty:r.Callbacks("once memory").add(function(){W.remove(a,[b+"queue",c])})})}}),r.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length<c?r.queue(this[0],a):void 0===b?this:this.each(function(){var c=r.queue(this,a,b);r._queueHooks(this,a),"fx"===a&&"inprogress"!==c[0]&&r.dequeue(this,a)})},dequeue:function(a){return this.each(function(){r.dequeue(this,a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,b){var c,d=1,e=r.Deferred(),f=this,g=this.length,h=function(){--d||e.resolveWith(f,[f])};"string"!=typeof a&&(b=a,a=void 0),a=a||"fx";while(g--)c=W.get(f[g],a+"queueHooks"),c&&c.empty&&(d++,c.empty.add(h));return h(),e.promise(b)}});var aa=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,ba=new RegExp("^(?:([+-])=|)("+aa+")([a-z%]*)$","i"),ca=["Top","Right","Bottom","Left"],da=function(a,b){return a=b||a,"none"===a.style.display||""===a.style.display&&r.contains(a.ownerDocument,a)&&"none"===r.css(a,"display")},ea=function(a,b,c,d){var e,f,g={};for(f in b)g[f]=a.style[f],a.style[f]=b[f];e=c.apply(a,d||[]);for(f in b)a.style[f]=g[f];return e};function fa(a,b,c,d){var e,f=1,g=20,h=d?function(){return d.cur()}:function(){return r.css(a,b,"")},i=h(),j=c&&c[3]||(r.cssNumber[b]?"":"px"),k=(r.cssNumber[b]||"px"!==j&&+i)&&ba.exec(r.css(a,b));if(k&&k[3]!==j){j=j||k[3],c=c||[],k=+i||1;do f=f||".5",k/=f,r.style(a,b,k+j);while(f!==(f=h()/i)&&1!==f&&--g)}return c&&(k=+k||+i||0,e=c[1]?k+(c[1]+1)*c[2]:+c[2],d&&(d.unit=j,d.start=k,d.end=e)),e}var ga={};function ha(a){var b,c=a.ownerDocument,d=a.nodeName,e=ga[d];return e?e:(b=c.body.appendChild(c.createElement(d)),e=r.css(b,"display"),b.parentNode.removeChild(b),"none"===e&&(e="block"),ga[d]=e,e)}function ia(a,b){for(var c,d,e=[],f=0,g=a.length;f<g;f++)d=a[f],d.style&&(c=d.style.display,b?("none"===c&&(e[f]=W.get(d,"display")||null,e[f]||(d.style.display="")),""===d.style.display&&da(d)&&(e[f]=ha(d))):"none"!==c&&(e[f]="none",W.set(d,"display",c)));for(f=0;f<g;f++)null!=e[f]&&(a[f].style.display=e[f]);return a}r.fn.extend({show:function(){return ia(this,!0)},hide:function(){return ia(this)},toggle:function(a){return"boolean"==typeof a?a?this.show():this.hide():this.each(function(){da(this)?r(this).show():r(this).hide()})}});var ja=/^(?:checkbox|radio)$/i,ka=/<([a-z][^\/\0>\x20\t\r\n\f]+)/i,la=/^$|\/(?:java|ecma)script/i,ma={option:[1,"<select multiple='multiple'>","</select>"],thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};ma.optgroup=ma.option,ma.tbody=ma.tfoot=ma.colgroup=ma.caption=ma.thead,ma.th=ma.td;function na(a,b){var c;return c="undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll(b||"*"):[],void 0===b||b&&B(a,b)?r.merge([a],c):c}function oa(a,b){for(var c=0,d=a.length;c<d;c++)W.set(a[c],"globalEval",!b||W.get(b[c],"globalEval"))}var pa=/<|&#?\w+;/;function qa(a,b,c,d,e){for(var f,g,h,i,j,k,l=b.createDocumentFragment(),m=[],n=0,o=a.length;n<o;n++)if(f=a[n],f||0===f)if("object"===r.type(f))r.merge(m,f.nodeType?[f]:f);else if(pa.test(f)){g=g||l.appendChild(b.createElement("div")),h=(ka.exec(f)||["",""])[1].toLowerCase(),i=ma[h]||ma._default,g.innerHTML=i[1]+r.htmlPrefilter(f)+i[2],k=i[0];while(k--)g=g.lastChild;r.merge(m,g.childNodes),g=l.firstChild,g.textContent=""}else m.push(b.createTextNode(f));l.textContent="",n=0;while(f=m[n++])if(d&&r.inArray(f,d)>-1)e&&e.push(f);else if(j=r.contains(f.ownerDocument,f),g=na(l.appendChild(f),"script"),j&&oa(g),c){k=0;while(f=g[k++])la.test(f.type||"")&&c.push(f)}return l}!function(){var a=d.createDocumentFragment(),b=a.appendChild(d.createElement("div")),c=d.createElement("input");c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),b.appendChild(c),o.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,b.innerHTML="<textarea>x</textarea>",o.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var ra=d.documentElement,sa=/^key/,ta=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,ua=/^([^.]*)(?:\.(.+)|)/;function va(){return!0}function wa(){return!1}function xa(){try{return d.activeElement}catch(a){}}function ya(a,b,c,d,e,f){var g,h;if("object"==typeof b){"string"!=typeof c&&(d=d||c,c=void 0);for(h in b)ya(a,h,c,d,b[h],f);return a}if(null==d&&null==e?(e=c,d=c=void 0):null==e&&("string"==typeof c?(e=d,d=void 0):(e=d,d=c,c=void 0)),e===!1)e=wa;else if(!e)return a;return 1===f&&(g=e,e=function(a){return r().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=r.guid++)),a.each(function(){r.event.add(this,b,e,d,c)})}r.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q=W.get(a);if(q){c.handler&&(f=c,c=f.handler,e=f.selector),e&&r.find.matchesSelector(ra,e),c.guid||(c.guid=r.guid++),(i=q.events)||(i=q.events={}),(g=q.handle)||(g=q.handle=function(b){return"undefined"!=typeof r&&r.event.triggered!==b.type?r.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(L)||[""],j=b.length;while(j--)h=ua.exec(b[j])||[],n=p=h[1],o=(h[2]||"").split(".").sort(),n&&(l=r.event.special[n]||{},n=(e?l.delegateType:l.bindType)||n,l=r.event.special[n]||{},k=r.extend({type:n,origType:p,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&r.expr.match.needsContext.test(e),namespace:o.join(".")},f),(m=i[n])||(m=i[n]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,o,g)!==!1||a.addEventListener&&a.addEventListener(n,g)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),r.event.global[n]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q=W.hasData(a)&&W.get(a);if(q&&(i=q.events)){b=(b||"").match(L)||[""],j=b.length;while(j--)if(h=ua.exec(b[j])||[],n=p=h[1],o=(h[2]||"").split(".").sort(),n){l=r.event.special[n]||{},n=(d?l.delegateType:l.bindType)||n,m=i[n]||[],h=h[2]&&new RegExp("(^|\\.)"+o.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&p!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,o,q.handle)!==!1||r.removeEvent(a,n,q.handle),delete i[n])}else for(n in i)r.event.remove(a,n+b[j],c,d,!0);r.isEmptyObject(i)&&W.remove(a,"handle events")}},dispatch:function(a){var b=r.event.fix(a),c,d,e,f,g,h,i=new Array(arguments.length),j=(W.get(this,"events")||{})[b.type]||[],k=r.event.special[b.type]||{};for(i[0]=b,c=1;c<arguments.length;c++)i[c]=arguments[c];if(b.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,b)!==!1){h=r.event.handlers.call(this,b,j),c=0;while((f=h[c++])&&!b.isPropagationStopped()){b.currentTarget=f.elem,d=0;while((g=f.handlers[d++])&&!b.isImmediatePropagationStopped())b.rnamespace&&!b.rnamespace.test(g.namespace)||(b.handleObj=g,b.data=g.data,e=((r.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==e&&(b.result=e)===!1&&(b.preventDefault(),b.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,b),b.result}},handlers:function(a,b){var c,d,e,f,g,h=[],i=b.delegateCount,j=a.target;if(i&&j.nodeType&&!("click"===a.type&&a.button>=1))for(;j!==this;j=j.parentNode||this)if(1===j.nodeType&&("click"!==a.type||j.disabled!==!0)){for(f=[],g={},c=0;c<i;c++)d=b[c],e=d.selector+" ",void 0===g[e]&&(g[e]=d.needsContext?r(e,this).index(j)>-1:r.find(e,this,null,[j]).length),g[e]&&f.push(d);f.length&&h.push({elem:j,handlers:f})}return j=this,i<b.length&&h.push({elem:j,handlers:b.slice(i)}),h},addProp:function(a,b){Object.defineProperty(r.Event.prototype,a,{enumerable:!0,configurable:!0,get:r.isFunction(b)?function(){if(this.originalEvent)return b(this.originalEvent)}:function(){if(this.originalEvent)return this.originalEvent[a]},set:function(b){Object.defineProperty(this,a,{enumerable:!0,configurable:!0,writable:!0,value:b})}})},fix:function(a){return a[r.expando]?a:new r.Event(a)},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==xa()&&this.focus)return this.focus(),!1},delegateType:"focusin"},blur:{trigger:function(){if(this===xa()&&this.blur)return this.blur(),!1},delegateType:"focusout"},click:{trigger:function(){if("checkbox"===this.type&&this.click&&B(this,"input"))return this.click(),!1},_default:function(a){return B(a.target,"a")}},beforeunload:{postDispatch:function(a){void 0!==a.result&&a.originalEvent&&(a.originalEvent.returnValue=a.result)}}}},r.removeEvent=function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c)},r.Event=function(a,b){return this instanceof r.Event?(a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||void 0===a.defaultPrevented&&a.returnValue===!1?va:wa,this.target=a.target&&3===a.target.nodeType?a.target.parentNode:a.target,this.currentTarget=a.currentTarget,this.relatedTarget=a.relatedTarget):this.type=a,b&&r.extend(this,b),this.timeStamp=a&&a.timeStamp||r.now(),void(this[r.expando]=!0)):new r.Event(a,b)},r.Event.prototype={constructor:r.Event,isDefaultPrevented:wa,isPropagationStopped:wa,isImmediatePropagationStopped:wa,isSimulated:!1,preventDefault:function(){var a=this.originalEvent;this.isDefaultPrevented=va,a&&!this.isSimulated&&a.preventDefault()},stopPropagation:function(){var a=this.originalEvent;this.isPropagationStopped=va,a&&!this.isSimulated&&a.stopPropagation()},stopImmediatePropagation:function(){var a=this.originalEvent;this.isImmediatePropagationStopped=va,a&&!this.isSimulated&&a.stopImmediatePropagation(),this.stopPropagation()}},r.each({altKey:!0,bubbles:!0,cancelable:!0,changedTouches:!0,ctrlKey:!0,detail:!0,eventPhase:!0,metaKey:!0,pageX:!0,pageY:!0,shiftKey:!0,view:!0,"char":!0,charCode:!0,key:!0,keyCode:!0,button:!0,buttons:!0,clientX:!0,clientY:!0,offsetX:!0,offsetY:!0,pointerId:!0,pointerType:!0,screenX:!0,screenY:!0,targetTouches:!0,toElement:!0,touches:!0,which:function(a){var b=a.button;return null==a.which&&sa.test(a.type)?null!=a.charCode?a.charCode:a.keyCode:!a.which&&void 0!==b&&ta.test(a.type)?1&b?1:2&b?3:4&b?2:0:a.which}},r.event.addProp),r.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(a,b){r.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj;return e&&(e===d||r.contains(d,e))||(a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b),c}}}),r.fn.extend({on:function(a,b,c,d){return ya(this,a,b,c,d)},one:function(a,b,c,d){return ya(this,a,b,c,d,1)},off:function(a,b,c){var d,e;if(a&&a.preventDefault&&a.handleObj)return d=a.handleObj,r(a.delegateTarget).off(d.namespace?d.origType+"."+d.namespace:d.origType,d.selector,d.handler),this;if("object"==typeof a){for(e in a)this.off(e,b,a[e]);return this}return b!==!1&&"function"!=typeof b||(c=b,b=void 0),c===!1&&(c=wa),this.each(function(){r.event.remove(this,a,c,b)})}});var za=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi,Aa=/<script|<style|<link/i,Ba=/checked\s*(?:[^=]|=\s*.checked.)/i,Ca=/^true\/(.*)/,Da=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;function Ea(a,b){return B(a,"table")&&B(11!==b.nodeType?b:b.firstChild,"tr")?r(">tbody",a)[0]||a:a}function Fa(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function Ga(a){var b=Ca.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function Ha(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(W.hasData(a)&&(f=W.access(a),g=W.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;c<d;c++)r.event.add(b,e,j[e][c])}X.hasData(a)&&(h=X.access(a),i=r.extend({},h),X.set(b,i))}}function Ia(a,b){var c=b.nodeName.toLowerCase();"input"===c&&ja.test(a.type)?b.checked=a.checked:"input"!==c&&"textarea"!==c||(b.defaultValue=a.defaultValue)}function Ja(a,b,c,d){b=g.apply([],b);var e,f,h,i,j,k,l=0,m=a.length,n=m-1,q=b[0],s=r.isFunction(q);if(s||m>1&&"string"==typeof q&&!o.checkClone&&Ba.test(q))return a.each(function(e){var f=a.eq(e);s&&(b[0]=q.call(this,e,f.html())),Ja(f,b,c,d)});if(m&&(e=qa(b,a[0].ownerDocument,!1,a,d),f=e.firstChild,1===e.childNodes.length&&(e=f),f||d)){for(h=r.map(na(e,"script"),Fa),i=h.length;l<m;l++)j=e,l!==n&&(j=r.clone(j,!0,!0),i&&r.merge(h,na(j,"script"))),c.call(a[l],j,l);if(i)for(k=h[h.length-1].ownerDocument,r.map(h,Ga),l=0;l<i;l++)j=h[l],la.test(j.type||"")&&!W.access(j,"globalEval")&&r.contains(k,j)&&(j.src?r._evalUrl&&r._evalUrl(j.src):p(j.textContent.replace(Da,""),k))}return a}function Ka(a,b,c){for(var d,e=b?r.filter(b,a):a,f=0;null!=(d=e[f]);f++)c||1!==d.nodeType||r.cleanData(na(d)),d.parentNode&&(c&&r.contains(d.ownerDocument,d)&&oa(na(d,"script")),d.parentNode.removeChild(d));return a}r.extend({htmlPrefilter:function(a){return a.replace(za,"<$1></$2>")},clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=r.contains(a.ownerDocument,a);if(!(o.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||r.isXMLDoc(a)))for(g=na(h),f=na(a),d=0,e=f.length;d<e;d++)Ia(f[d],g[d]);if(b)if(c)for(f=f||na(a),g=g||na(h),d=0,e=f.length;d<e;d++)Ha(f[d],g[d]);else Ha(a,h);return g=na(h,"script"),g.length>0&&oa(g,!i&&na(a,"script")),h},cleanData:function(a){for(var b,c,d,e=r.event.special,f=0;void 0!==(c=a[f]);f++)if(U(c)){if(b=c[W.expando]){if(b.events)for(d in b.events)e[d]?r.event.remove(c,d):r.removeEvent(c,d,b.handle);c[W.expando]=void 0}c[X.expando]&&(c[X.expando]=void 0)}}}),r.fn.extend({detach:function(a){return Ka(this,a,!0)},remove:function(a){return Ka(this,a)},text:function(a){return T(this,function(a){return void 0===a?r.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=a)})},null,a,arguments.length)},append:function(){return Ja(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ea(this,a);b.appendChild(a)}})},prepend:function(){return Ja(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ea(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return Ja(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return Ja(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(r.cleanData(na(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null!=a&&a,b=null==b?a:b,this.map(function(){return r.clone(this,a,b)})},html:function(a){return T(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!Aa.test(a)&&!ma[(ka.exec(a)||["",""])[1].toLowerCase()]){a=r.htmlPrefilter(a);try{for(;c<d;c++)b=this[c]||{},1===b.nodeType&&(r.cleanData(na(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=[];return Ja(this,arguments,function(b){var c=this.parentNode;r.inArray(this,a)<0&&(r.cleanData(na(this)),c&&c.replaceChild(b,this))},a)}}),r.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){r.fn[a]=function(a){for(var c,d=[],e=r(a),f=e.length-1,g=0;g<=f;g++)c=g===f?this:this.clone(!0),r(e[g])[b](c),h.apply(d,c.get());return this.pushStack(d)}});var La=/^margin/,Ma=new RegExp("^("+aa+")(?!px)[a-z%]+$","i"),Na=function(b){var c=b.ownerDocument.defaultView;return c&&c.opener||(c=a),c.getComputedStyle(b)};!function(){function b(){if(i){i.style.cssText="box-sizing:border-box;position:relative;display:block;margin:auto;border:1px;padding:1px;top:1%;width:50%",i.innerHTML="",ra.appendChild(h);var b=a.getComputedStyle(i);c="1%"!==b.top,g="2px"===b.marginLeft,e="4px"===b.width,i.style.marginRight="50%",f="4px"===b.marginRight,ra.removeChild(h),i=null}}var c,e,f,g,h=d.createElement("div"),i=d.createElement("div");i.style&&(i.style.backgroundClip="content-box",i.cloneNode(!0).style.backgroundClip="",o.clearCloneStyle="content-box"===i.style.backgroundClip,h.style.cssText="border:0;width:8px;height:0;top:0;left:-9999px;padding:0;margin-top:1px;position:absolute",h.appendChild(i),r.extend(o,{pixelPosition:function(){return b(),c},boxSizingReliable:function(){return b(),e},pixelMarginRight:function(){return b(),f},reliableMarginLeft:function(){return b(),g}}))}();function Oa(a,b,c){var d,e,f,g,h=a.style;return c=c||Na(a),c&&(g=c.getPropertyValue(b)||c[b],""!==g||r.contains(a.ownerDocument,a)||(g=r.style(a,b)),!o.pixelMarginRight()&&Ma.test(g)&&La.test(b)&&(d=h.width,e=h.minWidth,f=h.maxWidth,h.minWidth=h.maxWidth=h.width=g,g=c.width,h.width=d,h.minWidth=e,h.maxWidth=f)),void 0!==g?g+"":g}function Pa(a,b){return{get:function(){return a()?void delete this.get:(this.get=b).apply(this,arguments)}}}var Qa=/^(none|table(?!-c[ea]).+)/,Ra=/^--/,Sa={position:"absolute",visibility:"hidden",display:"block"},Ta={letterSpacing:"0",fontWeight:"400"},Ua=["Webkit","Moz","ms"],Va=d.createElement("div").style;function Wa(a){if(a in Va)return a;var b=a[0].toUpperCase()+a.slice(1),c=Ua.length;while(c--)if(a=Ua[c]+b,a in Va)return a}function Xa(a){var b=r.cssProps[a];return b||(b=r.cssProps[a]=Wa(a)||a),b}function Ya(a,b,c){var d=ba.exec(b);return d?Math.max(0,d[2]-(c||0))+(d[3]||"px"):b}function Za(a,b,c,d,e){var f,g=0;for(f=c===(d?"border":"content")?4:"width"===b?1:0;f<4;f+=2)"margin"===c&&(g+=r.css(a,c+ca[f],!0,e)),d?("content"===c&&(g-=r.css(a,"padding"+ca[f],!0,e)),"margin"!==c&&(g-=r.css(a,"border"+ca[f]+"Width",!0,e))):(g+=r.css(a,"padding"+ca[f],!0,e),"padding"!==c&&(g+=r.css(a,"border"+ca[f]+"Width",!0,e)));return g}function $a(a,b,c){var d,e=Na(a),f=Oa(a,b,e),g="border-box"===r.css(a,"boxSizing",!1,e);return Ma.test(f)?f:(d=g&&(o.boxSizingReliable()||f===a.style[b]),"auto"===f&&(f=a["offset"+b[0].toUpperCase()+b.slice(1)]),f=parseFloat(f)||0,f+Za(a,b,c||(g?"border":"content"),d,e)+"px")}r.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=Oa(a,"opacity");return""===c?"1":c}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":"cssFloat"},style:function(a,b,c,d){if(a&&3!==a.nodeType&&8!==a.nodeType&&a.style){var e,f,g,h=r.camelCase(b),i=Ra.test(b),j=a.style;return i||(b=Xa(h)),g=r.cssHooks[b]||r.cssHooks[h],void 0===c?g&&"get"in g&&void 0!==(e=g.get(a,!1,d))?e:j[b]:(f=typeof c,"string"===f&&(e=ba.exec(c))&&e[1]&&(c=fa(a,b,e),f="number"),null!=c&&c===c&&("number"===f&&(c+=e&&e[3]||(r.cssNumber[h]?"":"px")),o.clearCloneStyle||""!==c||0!==b.indexOf("background")||(j[b]="inherit"),g&&"set"in g&&void 0===(c=g.set(a,c,d))||(i?j.setProperty(b,c):j[b]=c)),void 0)}},css:function(a,b,c,d){var e,f,g,h=r.camelCase(b),i=Ra.test(b);return i||(b=Xa(h)),g=r.cssHooks[b]||r.cssHooks[h],g&&"get"in g&&(e=g.get(a,!0,c)),void 0===e&&(e=Oa(a,b,d)),"normal"===e&&b in Ta&&(e=Ta[b]),""===c||c?(f=parseFloat(e),c===!0||isFinite(f)?f||0:e):e}}),r.each(["height","width"],function(a,b){r.cssHooks[b]={get:function(a,c,d){if(c)return!Qa.test(r.css(a,"display"))||a.getClientRects().length&&a.getBoundingClientRect().width?$a(a,b,d):ea(a,Sa,function(){return $a(a,b,d)})},set:function(a,c,d){var e,f=d&&Na(a),g=d&&Za(a,b,d,"border-box"===r.css(a,"boxSizing",!1,f),f);return g&&(e=ba.exec(c))&&"px"!==(e[3]||"px")&&(a.style[b]=c,c=r.css(a,b)),Ya(a,c,g)}}}),r.cssHooks.marginLeft=Pa(o.reliableMarginLeft,function(a,b){if(b)return(parseFloat(Oa(a,"marginLeft"))||a.getBoundingClientRect().left-ea(a,{marginLeft:0},function(){return a.getBoundingClientRect().left}))+"px"}),r.each({margin:"",padding:"",border:"Width"},function(a,b){r.cssHooks[a+b]={expand:function(c){for(var d=0,e={},f="string"==typeof c?c.split(" "):[c];d<4;d++)e[a+ca[d]+b]=f[d]||f[d-2]||f[0];return e}},La.test(a)||(r.cssHooks[a+b].set=Ya)}),r.fn.extend({css:function(a,b){return T(this,function(a,b,c){var d,e,f={},g=0;if(Array.isArray(b)){for(d=Na(a),e=b.length;g<e;g++)f[b[g]]=r.css(a,b[g],!1,d);return f}return void 0!==c?r.style(a,b,c):r.css(a,b)},a,b,arguments.length>1)}});function _a(a,b,c,d,e){return new _a.prototype.init(a,b,c,d,e)}r.Tween=_a,_a.prototype={constructor:_a,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||r.easing._default,this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(r.cssNumber[c]?"":"px")},cur:function(){var a=_a.propHooks[this.prop];return a&&a.get?a.get(this):_a.propHooks._default.get(this)},run:function(a){var b,c=_a.propHooks[this.prop];return this.options.duration?this.pos=b=r.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):this.pos=b=a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):_a.propHooks._default.set(this),this}},_a.prototype.init.prototype=_a.prototype,_a.propHooks={_default:{get:function(a){var b;return 1!==a.elem.nodeType||null!=a.elem[a.prop]&&null==a.elem.style[a.prop]?a.elem[a.prop]:(b=r.css(a.elem,a.prop,""),b&&"auto"!==b?b:0)},set:function(a){r.fx.step[a.prop]?r.fx.step[a.prop](a):1!==a.elem.nodeType||null==a.elem.style[r.cssProps[a.prop]]&&!r.cssHooks[a.prop]?a.elem[a.prop]=a.now:r.style(a.elem,a.prop,a.now+a.unit)}}},_a.propHooks.scrollTop=_a.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},r.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2},_default:"swing"},r.fx=_a.prototype.init,r.fx.step={};var ab,bb,cb=/^(?:toggle|show|hide)$/,db=/queueHooks$/;function eb(){bb&&(d.hidden===!1&&a.requestAnimationFrame?a.requestAnimationFrame(eb):a.setTimeout(eb,r.fx.interval),r.fx.tick())}function fb(){return a.setTimeout(function(){ab=void 0}),ab=r.now()}function gb(a,b){var c,d=0,e={height:a};for(b=b?1:0;d<4;d+=2-b)c=ca[d],e["margin"+c]=e["padding"+c]=a;return b&&(e.opacity=e.width=a),e}function hb(a,b,c){for(var d,e=(kb.tweeners[b]||[]).concat(kb.tweeners["*"]),f=0,g=e.length;f<g;f++)if(d=e[f].call(c,b,a))return d}function ib(a,b,c){var d,e,f,g,h,i,j,k,l="width"in b||"height"in b,m=this,n={},o=a.style,p=a.nodeType&&da(a),q=W.get(a,"fxshow");c.queue||(g=r._queueHooks(a,"fx"),null==g.unqueued&&(g.unqueued=0,h=g.empty.fire,g.empty.fire=function(){g.unqueued||h()}),g.unqueued++,m.always(function(){m.always(function(){g.unqueued--,r.queue(a,"fx").length||g.empty.fire()})}));for(d in b)if(e=b[d],cb.test(e)){if(delete b[d],f=f||"toggle"===e,e===(p?"hide":"show")){if("show"!==e||!q||void 0===q[d])continue;p=!0}n[d]=q&&q[d]||r.style(a,d)}if(i=!r.isEmptyObject(b),i||!r.isEmptyObject(n)){l&&1===a.nodeType&&(c.overflow=[o.overflow,o.overflowX,o.overflowY],j=q&&q.display,null==j&&(j=W.get(a,"display")),k=r.css(a,"display"),"none"===k&&(j?k=j:(ia([a],!0),j=a.style.display||j,k=r.css(a,"display"),ia([a]))),("inline"===k||"inline-block"===k&&null!=j)&&"none"===r.css(a,"float")&&(i||(m.done(function(){o.display=j}),null==j&&(k=o.display,j="none"===k?"":k)),o.display="inline-block")),c.overflow&&(o.overflow="hidden",m.always(function(){o.overflow=c.overflow[0],o.overflowX=c.overflow[1],o.overflowY=c.overflow[2]})),i=!1;for(d in n)i||(q?"hidden"in q&&(p=q.hidden):q=W.access(a,"fxshow",{display:j}),f&&(q.hidden=!p),p&&ia([a],!0),m.done(function(){p||ia([a]),W.remove(a,"fxshow");for(d in n)r.style(a,d,n[d])})),i=hb(p?q[d]:0,d,m),d in q||(q[d]=i.start,p&&(i.end=i.start,i.start=0))}}function jb(a,b){var c,d,e,f,g;for(c in a)if(d=r.camelCase(c),e=b[d],f=a[c],Array.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=r.cssHooks[d],g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}function kb(a,b,c){var d,e,f=0,g=kb.prefilters.length,h=r.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=ab||fb(),c=Math.max(0,j.startTime+j.duration-b),d=c/j.duration||0,f=1-d,g=0,i=j.tweens.length;g<i;g++)j.tweens[g].run(f);return h.notifyWith(a,[j,f,c]),f<1&&i?c:(i||h.notifyWith(a,[j,1,0]),h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:r.extend({},b),opts:r.extend(!0,{specialEasing:{},easing:r.easing._default},c),originalProperties:b,originalOptions:c,startTime:ab||fb(),duration:c.duration,tweens:[],createTween:function(b,c){var d=r.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(d),d},stop:function(b){var c=0,d=b?j.tweens.length:0;if(e)return this;for(e=!0;c<d;c++)j.tweens[c].run(1);return b?(h.notifyWith(a,[j,1,0]),h.resolveWith(a,[j,b])):h.rejectWith(a,[j,b]),this}}),k=j.props;for(jb(k,j.opts.specialEasing);f<g;f++)if(d=kb.prefilters[f].call(j,a,k,j.opts))return r.isFunction(d.stop)&&(r._queueHooks(j.elem,j.opts.queue).stop=r.proxy(d.stop,d)),d;return r.map(k,hb,j),r.isFunction(j.opts.start)&&j.opts.start.call(a,j),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always),r.fx.timer(r.extend(i,{elem:a,anim:j,queue:j.opts.queue})),j}r.Animation=r.extend(kb,{tweeners:{"*":[function(a,b){var c=this.createTween(a,b);return fa(c.elem,a,ba.exec(b),c),c}]},tweener:function(a,b){r.isFunction(a)?(b=a,a=["*"]):a=a.match(L);for(var c,d=0,e=a.length;d<e;d++)c=a[d],kb.tweeners[c]=kb.tweeners[c]||[],kb.tweeners[c].unshift(b)},prefilters:[ib],prefilter:function(a,b){b?kb.prefilters.unshift(a):kb.prefilters.push(a)}}),r.speed=function(a,b,c){var d=a&&"object"==typeof a?r.extend({},a):{complete:c||!c&&b||r.isFunction(a)&&a,duration:a,easing:c&&b||b&&!r.isFunction(b)&&b};return r.fx.off?d.duration=0:"number"!=typeof d.duration&&(d.duration in r.fx.speeds?d.duration=r.fx.speeds[d.duration]:d.duration=r.fx.speeds._default),null!=d.queue&&d.queue!==!0||(d.queue="fx"),d.old=d.complete,d.complete=function(){r.isFunction(d.old)&&d.old.call(this),d.queue&&r.dequeue(this,d.queue)},d},r.fn.extend({fadeTo:function(a,b,c,d){return this.filter(da).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=r.isEmptyObject(a),f=r.speed(b,c,d),g=function(){var b=kb(this,r.extend({},a),f);(e||W.get(this,"finish"))&&b.stop(!0)};return g.finish=g,e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,b,c){var d=function(a){var b=a.stop;delete a.stop,b(c)};return"string"!=typeof a&&(c=b,b=a,a=void 0),b&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,e=null!=a&&a+"queueHooks",f=r.timers,g=W.get(this);if(e)g[e]&&g[e].stop&&d(g[e]);else for(e in g)g[e]&&g[e].stop&&db.test(e)&&d(g[e]);for(e=f.length;e--;)f[e].elem!==this||null!=a&&f[e].queue!==a||(f[e].anim.stop(c),b=!1,f.splice(e,1));!b&&c||r.dequeue(this,a)})},finish:function(a){return a!==!1&&(a=a||"fx"),this.each(function(){var b,c=W.get(this),d=c[a+"queue"],e=c[a+"queueHooks"],f=r.timers,g=d?d.length:0;for(c.finish=!0,r.queue(this,a,[]),e&&e.stop&&e.stop.call(this,!0),b=f.length;b--;)f[b].elem===this&&f[b].queue===a&&(f[b].anim.stop(!0),f.splice(b,1));for(b=0;b<g;b++)d[b]&&d[b].finish&&d[b].finish.call(this);delete c.finish})}}),r.each(["toggle","show","hide"],function(a,b){var c=r.fn[b];r.fn[b]=function(a,d,e){return null==a||"boolean"==typeof a?c.apply(this,arguments):this.animate(gb(b,!0),a,d,e)}}),r.each({slideDown:gb("show"),slideUp:gb("hide"),slideToggle:gb("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){r.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),r.timers=[],r.fx.tick=function(){var a,b=0,c=r.timers;for(ab=r.now();b<c.length;b++)a=c[b],a()||c[b]!==a||c.splice(b--,1);c.length||r.fx.stop(),ab=void 0},r.fx.timer=function(a){r.timers.push(a),r.fx.start()},r.fx.interval=13,r.fx.start=function(){bb||(bb=!0,eb())},r.fx.stop=function(){bb=null},r.fx.speeds={slow:600,fast:200,_default:400},r.fn.delay=function(b,c){return b=r.fx?r.fx.speeds[b]||b:b,c=c||"fx",this.queue(c,function(c,d){var e=a.setTimeout(c,b);d.stop=function(){a.clearTimeout(e)}})},function(){var a=d.createElement("input"),b=d.createElement("select"),c=b.appendChild(d.createElement("option"));a.type="checkbox",o.checkOn=""!==a.value,o.optSelected=c.selected,a=d.createElement("input"),a.value="t",a.type="radio",o.radioValue="t"===a.value}();var lb,mb=r.expr.attrHandle;r.fn.extend({attr:function(a,b){return T(this,r.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){r.removeAttr(this,a)})}}),r.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return"undefined"==typeof a.getAttribute?r.prop(a,b,c):(1===f&&r.isXMLDoc(a)||(e=r.attrHooks[b.toLowerCase()]||(r.expr.match.bool.test(b)?lb:void 0)),void 0!==c?null===c?void r.removeAttr(a,b):e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:(a.setAttribute(b,c+""),c):e&&"get"in e&&null!==(d=e.get(a,b))?d:(d=r.find.attr(a,b),
|
| 4 |
+
null==d?void 0:d))},attrHooks:{type:{set:function(a,b){if(!o.radioValue&&"radio"===b&&B(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}},removeAttr:function(a,b){var c,d=0,e=b&&b.match(L);if(e&&1===a.nodeType)while(c=e[d++])a.removeAttribute(c)}}),lb={set:function(a,b,c){return b===!1?r.removeAttr(a,c):a.setAttribute(c,c),c}},r.each(r.expr.match.bool.source.match(/\w+/g),function(a,b){var c=mb[b]||r.find.attr;mb[b]=function(a,b,d){var e,f,g=b.toLowerCase();return d||(f=mb[g],mb[g]=e,e=null!=c(a,b,d)?g:null,mb[g]=f),e}});var nb=/^(?:input|select|textarea|button)$/i,ob=/^(?:a|area)$/i;r.fn.extend({prop:function(a,b){return T(this,r.prop,a,b,arguments.length>1)},removeProp:function(a){return this.each(function(){delete this[r.propFix[a]||a]})}}),r.extend({prop:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return 1===f&&r.isXMLDoc(a)||(b=r.propFix[b]||b,e=r.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){var b=r.find.attr(a,"tabindex");return b?parseInt(b,10):nb.test(a.nodeName)||ob.test(a.nodeName)&&a.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),o.optSelected||(r.propHooks.selected={get:function(a){var b=a.parentNode;return b&&b.parentNode&&b.parentNode.selectedIndex,null},set:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex)}}),r.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){r.propFix[this.toLowerCase()]=this});function pb(a){var b=a.match(L)||[];return b.join(" ")}function qb(a){return a.getAttribute&&a.getAttribute("class")||""}r.fn.extend({addClass:function(a){var b,c,d,e,f,g,h,i=0;if(r.isFunction(a))return this.each(function(b){r(this).addClass(a.call(this,b,qb(this)))});if("string"==typeof a&&a){b=a.match(L)||[];while(c=this[i++])if(e=qb(c),d=1===c.nodeType&&" "+pb(e)+" "){g=0;while(f=b[g++])d.indexOf(" "+f+" ")<0&&(d+=f+" ");h=pb(d),e!==h&&c.setAttribute("class",h)}}return this},removeClass:function(a){var b,c,d,e,f,g,h,i=0;if(r.isFunction(a))return this.each(function(b){r(this).removeClass(a.call(this,b,qb(this)))});if(!arguments.length)return this.attr("class","");if("string"==typeof a&&a){b=a.match(L)||[];while(c=this[i++])if(e=qb(c),d=1===c.nodeType&&" "+pb(e)+" "){g=0;while(f=b[g++])while(d.indexOf(" "+f+" ")>-1)d=d.replace(" "+f+" "," ");h=pb(d),e!==h&&c.setAttribute("class",h)}}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):r.isFunction(a)?this.each(function(c){r(this).toggleClass(a.call(this,c,qb(this),b),b)}):this.each(function(){var b,d,e,f;if("string"===c){d=0,e=r(this),f=a.match(L)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else void 0!==a&&"boolean"!==c||(b=qb(this),b&&W.set(this,"__className__",b),this.setAttribute&&this.setAttribute("class",b||a===!1?"":W.get(this,"__className__")||""))})},hasClass:function(a){var b,c,d=0;b=" "+a+" ";while(c=this[d++])if(1===c.nodeType&&(" "+pb(qb(c))+" ").indexOf(b)>-1)return!0;return!1}});var rb=/\r/g;r.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=r.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,r(this).val()):a,null==e?e="":"number"==typeof e?e+="":Array.isArray(e)&&(e=r.map(e,function(a){return null==a?"":a+""})),b=r.valHooks[this.type]||r.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=r.valHooks[e.type]||r.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(rb,""):null==c?"":c)}}}),r.extend({valHooks:{option:{get:function(a){var b=r.find.attr(a,"value");return null!=b?b:pb(r.text(a))}},select:{get:function(a){var b,c,d,e=a.options,f=a.selectedIndex,g="select-one"===a.type,h=g?null:[],i=g?f+1:e.length;for(d=f<0?i:g?f:0;d<i;d++)if(c=e[d],(c.selected||d===f)&&!c.disabled&&(!c.parentNode.disabled||!B(c.parentNode,"optgroup"))){if(b=r(c).val(),g)return b;h.push(b)}return h},set:function(a,b){var c,d,e=a.options,f=r.makeArray(b),g=e.length;while(g--)d=e[g],(d.selected=r.inArray(r.valHooks.option.get(d),f)>-1)&&(c=!0);return c||(a.selectedIndex=-1),f}}}}),r.each(["radio","checkbox"],function(){r.valHooks[this]={set:function(a,b){if(Array.isArray(b))return a.checked=r.inArray(r(a).val(),b)>-1}},o.checkOn||(r.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})});var sb=/^(?:focusinfocus|focusoutblur)$/;r.extend(r.event,{trigger:function(b,c,e,f){var g,h,i,j,k,m,n,o=[e||d],p=l.call(b,"type")?b.type:b,q=l.call(b,"namespace")?b.namespace.split("."):[];if(h=i=e=e||d,3!==e.nodeType&&8!==e.nodeType&&!sb.test(p+r.event.triggered)&&(p.indexOf(".")>-1&&(q=p.split("."),p=q.shift(),q.sort()),k=p.indexOf(":")<0&&"on"+p,b=b[r.expando]?b:new r.Event(p,"object"==typeof b&&b),b.isTrigger=f?2:3,b.namespace=q.join("."),b.rnamespace=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=e),c=null==c?[b]:r.makeArray(c,[b]),n=r.event.special[p]||{},f||!n.trigger||n.trigger.apply(e,c)!==!1)){if(!f&&!n.noBubble&&!r.isWindow(e)){for(j=n.delegateType||p,sb.test(j+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),i=h;i===(e.ownerDocument||d)&&o.push(i.defaultView||i.parentWindow||a)}g=0;while((h=o[g++])&&!b.isPropagationStopped())b.type=g>1?j:n.bindType||p,m=(W.get(h,"events")||{})[b.type]&&W.get(h,"handle"),m&&m.apply(h,c),m=k&&h[k],m&&m.apply&&U(h)&&(b.result=m.apply(h,c),b.result===!1&&b.preventDefault());return b.type=p,f||b.isDefaultPrevented()||n._default&&n._default.apply(o.pop(),c)!==!1||!U(e)||k&&r.isFunction(e[p])&&!r.isWindow(e)&&(i=e[k],i&&(e[k]=null),r.event.triggered=p,e[p](),r.event.triggered=void 0,i&&(e[k]=i)),b.result}},simulate:function(a,b,c){var d=r.extend(new r.Event,c,{type:a,isSimulated:!0});r.event.trigger(d,null,b)}}),r.fn.extend({trigger:function(a,b){return this.each(function(){r.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];if(c)return r.event.trigger(a,b,c,!0)}}),r.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(a,b){r.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),r.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),o.focusin="onfocusin"in a,o.focusin||r.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){r.event.simulate(b,a.target,r.event.fix(a))};r.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=W.access(d,b);e||d.addEventListener(a,c,!0),W.access(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=W.access(d,b)-1;e?W.access(d,b,e):(d.removeEventListener(a,c,!0),W.remove(d,b))}}});var tb=a.location,ub=r.now(),vb=/\?/;r.parseXML=function(b){var c;if(!b||"string"!=typeof b)return null;try{c=(new a.DOMParser).parseFromString(b,"text/xml")}catch(d){c=void 0}return c&&!c.getElementsByTagName("parsererror").length||r.error("Invalid XML: "+b),c};var wb=/\[\]$/,xb=/\r?\n/g,yb=/^(?:submit|button|image|reset|file)$/i,zb=/^(?:input|select|textarea|keygen)/i;function Ab(a,b,c,d){var e;if(Array.isArray(b))r.each(b,function(b,e){c||wb.test(a)?d(a,e):Ab(a+"["+("object"==typeof e&&null!=e?b:"")+"]",e,c,d)});else if(c||"object"!==r.type(b))d(a,b);else for(e in b)Ab(a+"["+e+"]",b[e],c,d)}r.param=function(a,b){var c,d=[],e=function(a,b){var c=r.isFunction(b)?b():b;d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(null==c?"":c)};if(Array.isArray(a)||a.jquery&&!r.isPlainObject(a))r.each(a,function(){e(this.name,this.value)});else for(c in a)Ab(c,a[c],b,e);return d.join("&")},r.fn.extend({serialize:function(){return r.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=r.prop(this,"elements");return a?r.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!r(this).is(":disabled")&&zb.test(this.nodeName)&&!yb.test(a)&&(this.checked||!ja.test(a))}).map(function(a,b){var c=r(this).val();return null==c?null:Array.isArray(c)?r.map(c,function(a){return{name:b.name,value:a.replace(xb,"\r\n")}}):{name:b.name,value:c.replace(xb,"\r\n")}}).get()}});var Bb=/%20/g,Cb=/#.*$/,Db=/([?&])_=[^&]*/,Eb=/^(.*?):[ \t]*([^\r\n]*)$/gm,Fb=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Gb=/^(?:GET|HEAD)$/,Hb=/^\/\//,Ib={},Jb={},Kb="*/".concat("*"),Lb=d.createElement("a");Lb.href=tb.href;function Mb(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(L)||[];if(r.isFunction(c))while(d=f[e++])"+"===d[0]?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function Nb(a,b,c,d){var e={},f=a===Jb;function g(h){var i;return e[h]=!0,r.each(a[h]||[],function(a,h){var j=h(b,c,d);return"string"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e["*"]&&g("*")}function Ob(a,b){var c,d,e=r.ajaxSettings.flatOptions||{};for(c in b)void 0!==b[c]&&((e[c]?a:d||(d={}))[c]=b[c]);return d&&r.extend(!0,a,d),a}function Pb(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===d&&(d=a.mimeType||b.getResponseHeader("Content-Type"));if(d)for(e in h)if(h[e]&&h[e].test(d)){i.unshift(e);break}if(i[0]in c)f=i[0];else{for(e in c){if(!i[0]||a.converters[e+" "+i[0]]){f=e;break}g||(g=e)}f=f||g}if(f)return f!==i[0]&&i.unshift(f),c[f]}function Qb(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if("*"===f)f=i;else if("*"!==i&&i!==f){if(g=j[i+" "+f]||j["* "+f],!g)for(e in j)if(h=e.split(" "),h[1]===f&&(g=j[i+" "+h[0]]||j["* "+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a["throws"])b=g(b);else try{b=g(b)}catch(l){return{state:"parsererror",error:g?l:"No conversion from "+i+" to "+f}}}return{state:"success",data:b}}r.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:tb.href,type:"GET",isLocal:Fb.test(tb.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Kb,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":r.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?Ob(Ob(a,r.ajaxSettings),b):Ob(r.ajaxSettings,a)},ajaxPrefilter:Mb(Ib),ajaxTransport:Mb(Jb),ajax:function(b,c){"object"==typeof b&&(c=b,b=void 0),c=c||{};var e,f,g,h,i,j,k,l,m,n,o=r.ajaxSetup({},c),p=o.context||o,q=o.context&&(p.nodeType||p.jquery)?r(p):r.event,s=r.Deferred(),t=r.Callbacks("once memory"),u=o.statusCode||{},v={},w={},x="canceled",y={readyState:0,getResponseHeader:function(a){var b;if(k){if(!h){h={};while(b=Eb.exec(g))h[b[1].toLowerCase()]=b[2]}b=h[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return k?g:null},setRequestHeader:function(a,b){return null==k&&(a=w[a.toLowerCase()]=w[a.toLowerCase()]||a,v[a]=b),this},overrideMimeType:function(a){return null==k&&(o.mimeType=a),this},statusCode:function(a){var b;if(a)if(k)y.always(a[y.status]);else for(b in a)u[b]=[u[b],a[b]];return this},abort:function(a){var b=a||x;return e&&e.abort(b),A(0,b),this}};if(s.promise(y),o.url=((b||o.url||tb.href)+"").replace(Hb,tb.protocol+"//"),o.type=c.method||c.type||o.method||o.type,o.dataTypes=(o.dataType||"*").toLowerCase().match(L)||[""],null==o.crossDomain){j=d.createElement("a");try{j.href=o.url,j.href=j.href,o.crossDomain=Lb.protocol+"//"+Lb.host!=j.protocol+"//"+j.host}catch(z){o.crossDomain=!0}}if(o.data&&o.processData&&"string"!=typeof o.data&&(o.data=r.param(o.data,o.traditional)),Nb(Ib,o,c,y),k)return y;l=r.event&&o.global,l&&0===r.active++&&r.event.trigger("ajaxStart"),o.type=o.type.toUpperCase(),o.hasContent=!Gb.test(o.type),f=o.url.replace(Cb,""),o.hasContent?o.data&&o.processData&&0===(o.contentType||"").indexOf("application/x-www-form-urlencoded")&&(o.data=o.data.replace(Bb,"+")):(n=o.url.slice(f.length),o.data&&(f+=(vb.test(f)?"&":"?")+o.data,delete o.data),o.cache===!1&&(f=f.replace(Db,"$1"),n=(vb.test(f)?"&":"?")+"_="+ub++ +n),o.url=f+n),o.ifModified&&(r.lastModified[f]&&y.setRequestHeader("If-Modified-Since",r.lastModified[f]),r.etag[f]&&y.setRequestHeader("If-None-Match",r.etag[f])),(o.data&&o.hasContent&&o.contentType!==!1||c.contentType)&&y.setRequestHeader("Content-Type",o.contentType),y.setRequestHeader("Accept",o.dataTypes[0]&&o.accepts[o.dataTypes[0]]?o.accepts[o.dataTypes[0]]+("*"!==o.dataTypes[0]?", "+Kb+"; q=0.01":""):o.accepts["*"]);for(m in o.headers)y.setRequestHeader(m,o.headers[m]);if(o.beforeSend&&(o.beforeSend.call(p,y,o)===!1||k))return y.abort();if(x="abort",t.add(o.complete),y.done(o.success),y.fail(o.error),e=Nb(Jb,o,c,y)){if(y.readyState=1,l&&q.trigger("ajaxSend",[y,o]),k)return y;o.async&&o.timeout>0&&(i=a.setTimeout(function(){y.abort("timeout")},o.timeout));try{k=!1,e.send(v,A)}catch(z){if(k)throw z;A(-1,z)}}else A(-1,"No Transport");function A(b,c,d,h){var j,m,n,v,w,x=c;k||(k=!0,i&&a.clearTimeout(i),e=void 0,g=h||"",y.readyState=b>0?4:0,j=b>=200&&b<300||304===b,d&&(v=Pb(o,y,d)),v=Qb(o,v,y,j),j?(o.ifModified&&(w=y.getResponseHeader("Last-Modified"),w&&(r.lastModified[f]=w),w=y.getResponseHeader("etag"),w&&(r.etag[f]=w)),204===b||"HEAD"===o.type?x="nocontent":304===b?x="notmodified":(x=v.state,m=v.data,n=v.error,j=!n)):(n=x,!b&&x||(x="error",b<0&&(b=0))),y.status=b,y.statusText=(c||x)+"",j?s.resolveWith(p,[m,x,y]):s.rejectWith(p,[y,x,n]),y.statusCode(u),u=void 0,l&&q.trigger(j?"ajaxSuccess":"ajaxError",[y,o,j?m:n]),t.fireWith(p,[y,x]),l&&(q.trigger("ajaxComplete",[y,o]),--r.active||r.event.trigger("ajaxStop")))}return y},getJSON:function(a,b,c){return r.get(a,b,c,"json")},getScript:function(a,b){return r.get(a,void 0,b,"script")}}),r.each(["get","post"],function(a,b){r[b]=function(a,c,d,e){return r.isFunction(c)&&(e=e||d,d=c,c=void 0),r.ajax(r.extend({url:a,type:b,dataType:e,data:c,success:d},r.isPlainObject(a)&&a))}}),r._evalUrl=function(a){return r.ajax({url:a,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,"throws":!0})},r.fn.extend({wrapAll:function(a){var b;return this[0]&&(r.isFunction(a)&&(a=a.call(this[0])),b=r(a,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstElementChild)a=a.firstElementChild;return a}).append(this)),this},wrapInner:function(a){return r.isFunction(a)?this.each(function(b){r(this).wrapInner(a.call(this,b))}):this.each(function(){var b=r(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=r.isFunction(a);return this.each(function(c){r(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(a){return this.parent(a).not("body").each(function(){r(this).replaceWith(this.childNodes)}),this}}),r.expr.pseudos.hidden=function(a){return!r.expr.pseudos.visible(a)},r.expr.pseudos.visible=function(a){return!!(a.offsetWidth||a.offsetHeight||a.getClientRects().length)},r.ajaxSettings.xhr=function(){try{return new a.XMLHttpRequest}catch(b){}};var Rb={0:200,1223:204},Sb=r.ajaxSettings.xhr();o.cors=!!Sb&&"withCredentials"in Sb,o.ajax=Sb=!!Sb,r.ajaxTransport(function(b){var c,d;if(o.cors||Sb&&!b.crossDomain)return{send:function(e,f){var g,h=b.xhr();if(h.open(b.type,b.url,b.async,b.username,b.password),b.xhrFields)for(g in b.xhrFields)h[g]=b.xhrFields[g];b.mimeType&&h.overrideMimeType&&h.overrideMimeType(b.mimeType),b.crossDomain||e["X-Requested-With"]||(e["X-Requested-With"]="XMLHttpRequest");for(g in e)h.setRequestHeader(g,e[g]);c=function(a){return function(){c&&(c=d=h.onload=h.onerror=h.onabort=h.onreadystatechange=null,"abort"===a?h.abort():"error"===a?"number"!=typeof h.status?f(0,"error"):f(h.status,h.statusText):f(Rb[h.status]||h.status,h.statusText,"text"!==(h.responseType||"text")||"string"!=typeof h.responseText?{binary:h.response}:{text:h.responseText},h.getAllResponseHeaders()))}},h.onload=c(),d=h.onerror=c("error"),void 0!==h.onabort?h.onabort=d:h.onreadystatechange=function(){4===h.readyState&&a.setTimeout(function(){c&&d()})},c=c("abort");try{h.send(b.hasContent&&b.data||null)}catch(i){if(c)throw i}},abort:function(){c&&c()}}}),r.ajaxPrefilter(function(a){a.crossDomain&&(a.contents.script=!1)}),r.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(a){return r.globalEval(a),a}}}),r.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET")}),r.ajaxTransport("script",function(a){if(a.crossDomain){var b,c;return{send:function(e,f){b=r("<script>").prop({charset:a.scriptCharset,src:a.url}).on("load error",c=function(a){b.remove(),c=null,a&&f("error"===a.type?404:200,a.type)}),d.head.appendChild(b[0])},abort:function(){c&&c()}}}});var Tb=[],Ub=/(=)\?(?=&|$)|\?\?/;r.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=Tb.pop()||r.expando+"_"+ub++;return this[a]=!0,a}}),r.ajaxPrefilter("json jsonp",function(b,c,d){var e,f,g,h=b.jsonp!==!1&&(Ub.test(b.url)?"url":"string"==typeof b.data&&0===(b.contentType||"").indexOf("application/x-www-form-urlencoded")&&Ub.test(b.data)&&"data");if(h||"jsonp"===b.dataTypes[0])return e=b.jsonpCallback=r.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,h?b[h]=b[h].replace(Ub,"$1"+e):b.jsonp!==!1&&(b.url+=(vb.test(b.url)?"&":"?")+b.jsonp+"="+e),b.converters["script json"]=function(){return g||r.error(e+" was not called"),g[0]},b.dataTypes[0]="json",f=a[e],a[e]=function(){g=arguments},d.always(function(){void 0===f?r(a).removeProp(e):a[e]=f,b[e]&&(b.jsonpCallback=c.jsonpCallback,Tb.push(e)),g&&r.isFunction(f)&&f(g[0]),g=f=void 0}),"script"}),o.createHTMLDocument=function(){var a=d.implementation.createHTMLDocument("").body;return a.innerHTML="<form></form><form></form>",2===a.childNodes.length}(),r.parseHTML=function(a,b,c){if("string"!=typeof a)return[];"boolean"==typeof b&&(c=b,b=!1);var e,f,g;return b||(o.createHTMLDocument?(b=d.implementation.createHTMLDocument(""),e=b.createElement("base"),e.href=d.location.href,b.head.appendChild(e)):b=d),f=C.exec(a),g=!c&&[],f?[b.createElement(f[1])]:(f=qa([a],b,g),g&&g.length&&r(g).remove(),r.merge([],f.childNodes))},r.fn.load=function(a,b,c){var d,e,f,g=this,h=a.indexOf(" ");return h>-1&&(d=pb(a.slice(h)),a=a.slice(0,h)),r.isFunction(b)?(c=b,b=void 0):b&&"object"==typeof b&&(e="POST"),g.length>0&&r.ajax({url:a,type:e||"GET",dataType:"html",data:b}).done(function(a){f=arguments,g.html(d?r("<div>").append(r.parseHTML(a)).find(d):a)}).always(c&&function(a,b){g.each(function(){c.apply(this,f||[a.responseText,b,a])})}),this},r.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(a,b){r.fn[b]=function(a){return this.on(b,a)}}),r.expr.pseudos.animated=function(a){return r.grep(r.timers,function(b){return a===b.elem}).length},r.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=r.css(a,"position"),l=r(a),m={};"static"===k&&(a.style.position="relative"),h=l.offset(),f=r.css(a,"top"),i=r.css(a,"left"),j=("absolute"===k||"fixed"===k)&&(f+i).indexOf("auto")>-1,j?(d=l.position(),g=d.top,e=d.left):(g=parseFloat(f)||0,e=parseFloat(i)||0),r.isFunction(b)&&(b=b.call(a,c,r.extend({},h))),null!=b.top&&(m.top=b.top-h.top+g),null!=b.left&&(m.left=b.left-h.left+e),"using"in b?b.using.call(a,m):l.css(m)}},r.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){r.offset.setOffset(this,a,b)});var b,c,d,e,f=this[0];if(f)return f.getClientRects().length?(d=f.getBoundingClientRect(),b=f.ownerDocument,c=b.documentElement,e=b.defaultView,{top:d.top+e.pageYOffset-c.clientTop,left:d.left+e.pageXOffset-c.clientLeft}):{top:0,left:0}},position:function(){if(this[0]){var a,b,c=this[0],d={top:0,left:0};return"fixed"===r.css(c,"position")?b=c.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),B(a[0],"html")||(d=a.offset()),d={top:d.top+r.css(a[0],"borderTopWidth",!0),left:d.left+r.css(a[0],"borderLeftWidth",!0)}),{top:b.top-d.top-r.css(c,"marginTop",!0),left:b.left-d.left-r.css(c,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent;while(a&&"static"===r.css(a,"position"))a=a.offsetParent;return a||ra})}}),r.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,b){var c="pageYOffset"===b;r.fn[a]=function(d){return T(this,function(a,d,e){var f;return r.isWindow(a)?f=a:9===a.nodeType&&(f=a.defaultView),void 0===e?f?f[b]:a[d]:void(f?f.scrollTo(c?f.pageXOffset:e,c?e:f.pageYOffset):a[d]=e)},a,d,arguments.length)}}),r.each(["top","left"],function(a,b){r.cssHooks[b]=Pa(o.pixelPosition,function(a,c){if(c)return c=Oa(a,b),Ma.test(c)?r(a).position()[b]+"px":c})}),r.each({Height:"height",Width:"width"},function(a,b){r.each({padding:"inner"+a,content:b,"":"outer"+a},function(c,d){r.fn[d]=function(e,f){var g=arguments.length&&(c||"boolean"!=typeof e),h=c||(e===!0||f===!0?"margin":"border");return T(this,function(b,c,e){var f;return r.isWindow(b)?0===d.indexOf("outer")?b["inner"+a]:b.document.documentElement["client"+a]:9===b.nodeType?(f=b.documentElement,Math.max(b.body["scroll"+a],f["scroll"+a],b.body["offset"+a],f["offset"+a],f["client"+a])):void 0===e?r.css(b,c,h):r.style(b,c,e,h)},b,g?e:void 0,g)}})}),r.fn.extend({bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return 1===arguments.length?this.off(a,"**"):this.off(b,a||"**",c)}}),r.holdReady=function(a){a?r.readyWait++:r.ready(!0)},r.isArray=Array.isArray,r.parseJSON=JSON.parse,r.nodeName=B,"function"==typeof define&&define.amd&&define("jquery",[],function(){return r});var Vb=a.jQuery,Wb=a.$;return r.noConflict=function(b){return a.$===r&&(a.$=Wb),b&&a.jQuery===r&&(a.jQuery=Vb),r},b||(a.jQuery=a.$=r),r});
|
src/arborator-draft/jszip.min.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*!
|
| 2 |
+
|
| 3 |
+
JSZip v3.3.0 - A JavaScript class for generating and reading zip files
|
| 4 |
+
<http://stuartk.com/jszip>
|
| 5 |
+
|
| 6 |
+
(c) 2009-2016 Stuart Knightley <stuart [at] stuartk.com>
|
| 7 |
+
Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip/master/LICENSE.markdown.
|
| 8 |
+
|
| 9 |
+
JSZip uses the library pako released under the MIT license :
|
| 10 |
+
https://github.com/nodeca/pako/blob/master/LICENSE
|
| 11 |
+
*/
|
| 12 |
+
|
| 13 |
+
!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).JSZip=t()}}(function(){return function s(a,o,h){function u(r,t){if(!o[r]){if(!a[r]){var e="function"==typeof require&&require;if(!t&&e)return e(r,!0);if(l)return l(r,!0);var i=new Error("Cannot find module '"+r+"'");throw i.code="MODULE_NOT_FOUND",i}var n=o[r]={exports:{}};a[r][0].call(n.exports,function(t){var e=a[r][1][t];return u(e||t)},n,n.exports,s,a,o,h)}return o[r].exports}for(var l="function"==typeof require&&require,t=0;t<h.length;t++)u(h[t]);return u}({1:[function(t,e,r){"use strict";var c=t("./utils"),d=t("./support"),p="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";r.encode=function(t){for(var e,r,i,n,s,a,o,h=[],u=0,l=t.length,f=l,d="string"!==c.getTypeOf(t);u<t.length;)f=l-u,i=d?(e=t[u++],r=u<l?t[u++]:0,u<l?t[u++]:0):(e=t.charCodeAt(u++),r=u<l?t.charCodeAt(u++):0,u<l?t.charCodeAt(u++):0),n=e>>2,s=(3&e)<<4|r>>4,a=1<f?(15&r)<<2|i>>6:64,o=2<f?63&i:64,h.push(p.charAt(n)+p.charAt(s)+p.charAt(a)+p.charAt(o));return h.join("")},r.decode=function(t){var e,r,i,n,s,a,o=0,h=0,u="data:";if(t.substr(0,u.length)===u)throw new Error("Invalid base64 input, it looks like a data url.");var l,f=3*(t=t.replace(/[^A-Za-z0-9\+\/\=]/g,"")).length/4;if(t.charAt(t.length-1)===p.charAt(64)&&f--,t.charAt(t.length-2)===p.charAt(64)&&f--,f%1!=0)throw new Error("Invalid base64 input, bad content length.");for(l=d.uint8array?new Uint8Array(0|f):new Array(0|f);o<t.length;)e=p.indexOf(t.charAt(o++))<<2|(n=p.indexOf(t.charAt(o++)))>>4,r=(15&n)<<4|(s=p.indexOf(t.charAt(o++)))>>2,i=(3&s)<<6|(a=p.indexOf(t.charAt(o++))),l[h++]=e,64!==s&&(l[h++]=r),64!==a&&(l[h++]=i);return l}},{"./support":30,"./utils":32}],2:[function(t,e,r){"use strict";var i=t("./external"),n=t("./stream/DataWorker"),s=t("./stream/DataLengthProbe"),a=t("./stream/Crc32Probe");s=t("./stream/DataLengthProbe");function o(t,e,r,i,n){this.compressedSize=t,this.uncompressedSize=e,this.crc32=r,this.compression=i,this.compressedContent=n}o.prototype={getContentWorker:function(){var t=new n(i.Promise.resolve(this.compressedContent)).pipe(this.compression.uncompressWorker()).pipe(new s("data_length")),e=this;return t.on("end",function(){if(this.streamInfo.data_length!==e.uncompressedSize)throw new Error("Bug : uncompressed data size mismatch")}),t},getCompressedWorker:function(){return new n(i.Promise.resolve(this.compressedContent)).withStreamInfo("compressedSize",this.compressedSize).withStreamInfo("uncompressedSize",this.uncompressedSize).withStreamInfo("crc32",this.crc32).withStreamInfo("compression",this.compression)}},o.createWorkerFrom=function(t,e,r){return t.pipe(new a).pipe(new s("uncompressedSize")).pipe(e.compressWorker(r)).pipe(new s("compressedSize")).withStreamInfo("compression",e)},e.exports=o},{"./external":6,"./stream/Crc32Probe":25,"./stream/DataLengthProbe":26,"./stream/DataWorker":27}],3:[function(t,e,r){"use strict";var i=t("./stream/GenericWorker");r.STORE={magic:"\0\0",compressWorker:function(t){return new i("STORE compression")},uncompressWorker:function(){return new i("STORE decompression")}},r.DEFLATE=t("./flate")},{"./flate":7,"./stream/GenericWorker":28}],4:[function(t,e,r){"use strict";var i=t("./utils");var o=function(){for(var t,e=[],r=0;r<256;r++){t=r;for(var i=0;i<8;i++)t=1&t?3988292384^t>>>1:t>>>1;e[r]=t}return e}();e.exports=function(t,e){return void 0!==t&&t.length?"string"!==i.getTypeOf(t)?function(t,e,r,i){var n=o,s=i+r;t^=-1;for(var a=i;a<s;a++)t=t>>>8^n[255&(t^e[a])];return-1^t}(0|e,t,t.length,0):function(t,e,r,i){var n=o,s=i+r;t^=-1;for(var a=i;a<s;a++)t=t>>>8^n[255&(t^e.charCodeAt(a))];return-1^t}(0|e,t,t.length,0):0}},{"./utils":32}],5:[function(t,e,r){"use strict";r.base64=!1,r.binary=!1,r.dir=!1,r.createFolders=!0,r.date=null,r.compression=null,r.compressionOptions=null,r.comment=null,r.unixPermissions=null,r.dosPermissions=null},{}],6:[function(t,e,r){"use strict";var i=null;i="undefined"!=typeof Promise?Promise:t("lie"),e.exports={Promise:i}},{lie:37}],7:[function(t,e,r){"use strict";var i="undefined"!=typeof Uint8Array&&"undefined"!=typeof Uint16Array&&"undefined"!=typeof Uint32Array,n=t("pako"),s=t("./utils"),a=t("./stream/GenericWorker"),o=i?"uint8array":"array";function h(t,e){a.call(this,"FlateWorker/"+t),this._pako=null,this._pakoAction=t,this._pakoOptions=e,this.meta={}}r.magic="\b\0",s.inherits(h,a),h.prototype.processChunk=function(t){this.meta=t.meta,null===this._pako&&this._createPako(),this._pako.push(s.transformTo(o,t.data),!1)},h.prototype.flush=function(){a.prototype.flush.call(this),null===this._pako&&this._createPako(),this._pako.push([],!0)},h.prototype.cleanUp=function(){a.prototype.cleanUp.call(this),this._pako=null},h.prototype._createPako=function(){this._pako=new n[this._pakoAction]({raw:!0,level:this._pakoOptions.level||-1});var e=this;this._pako.onData=function(t){e.push({data:t,meta:e.meta})}},r.compressWorker=function(t){return new h("Deflate",t)},r.uncompressWorker=function(){return new h("Inflate",{})}},{"./stream/GenericWorker":28,"./utils":32,pako:38}],8:[function(t,e,r){"use strict";function A(t,e){var r,i="";for(r=0;r<e;r++)i+=String.fromCharCode(255&t),t>>>=8;return i}function i(t,e,r,i,n,s){var a,o,h=t.file,u=t.compression,l=s!==O.utf8encode,f=I.transformTo("string",s(h.name)),d=I.transformTo("string",O.utf8encode(h.name)),c=h.comment,p=I.transformTo("string",s(c)),m=I.transformTo("string",O.utf8encode(c)),_=d.length!==h.name.length,g=m.length!==c.length,b="",v="",y="",w=h.dir,k=h.date,x={crc32:0,compressedSize:0,uncompressedSize:0};e&&!r||(x.crc32=t.crc32,x.compressedSize=t.compressedSize,x.uncompressedSize=t.uncompressedSize);var S=0;e&&(S|=8),l||!_&&!g||(S|=2048);var z=0,C=0;w&&(z|=16),"UNIX"===n?(C=798,z|=function(t,e){var r=t;return t||(r=e?16893:33204),(65535&r)<<16}(h.unixPermissions,w)):(C=20,z|=function(t){return 63&(t||0)}(h.dosPermissions)),a=k.getUTCHours(),a<<=6,a|=k.getUTCMinutes(),a<<=5,a|=k.getUTCSeconds()/2,o=k.getUTCFullYear()-1980,o<<=4,o|=k.getUTCMonth()+1,o<<=5,o|=k.getUTCDate(),_&&(v=A(1,1)+A(B(f),4)+d,b+="up"+A(v.length,2)+v),g&&(y=A(1,1)+A(B(p),4)+m,b+="uc"+A(y.length,2)+y);var E="";return E+="\n\0",E+=A(S,2),E+=u.magic,E+=A(a,2),E+=A(o,2),E+=A(x.crc32,4),E+=A(x.compressedSize,4),E+=A(x.uncompressedSize,4),E+=A(f.length,2),E+=A(b.length,2),{fileRecord:R.LOCAL_FILE_HEADER+E+f+b,dirRecord:R.CENTRAL_FILE_HEADER+A(C,2)+E+A(p.length,2)+"\0\0\0\0"+A(z,4)+A(i,4)+f+b+p}}var I=t("../utils"),n=t("../stream/GenericWorker"),O=t("../utf8"),B=t("../crc32"),R=t("../signature");function s(t,e,r,i){n.call(this,"ZipFileWorker"),this.bytesWritten=0,this.zipComment=e,this.zipPlatform=r,this.encodeFileName=i,this.streamFiles=t,this.accumulate=!1,this.contentBuffer=[],this.dirRecords=[],this.currentSourceOffset=0,this.entriesCount=0,this.currentFile=null,this._sources=[]}I.inherits(s,n),s.prototype.push=function(t){var e=t.meta.percent||0,r=this.entriesCount,i=this._sources.length;this.accumulate?this.contentBuffer.push(t):(this.bytesWritten+=t.data.length,n.prototype.push.call(this,{data:t.data,meta:{currentFile:this.currentFile,percent:r?(e+100*(r-i-1))/r:100}}))},s.prototype.openedSource=function(t){this.currentSourceOffset=this.bytesWritten,this.currentFile=t.file.name;var e=this.streamFiles&&!t.file.dir;if(e){var r=i(t,e,!1,this.currentSourceOffset,this.zipPlatform,this.encodeFileName);this.push({data:r.fileRecord,meta:{percent:0}})}else this.accumulate=!0},s.prototype.closedSource=function(t){this.accumulate=!1;var e=this.streamFiles&&!t.file.dir,r=i(t,e,!0,this.currentSourceOffset,this.zipPlatform,this.encodeFileName);if(this.dirRecords.push(r.dirRecord),e)this.push({data:function(t){return R.DATA_DESCRIPTOR+A(t.crc32,4)+A(t.compressedSize,4)+A(t.uncompressedSize,4)}(t),meta:{percent:100}});else for(this.push({data:r.fileRecord,meta:{percent:0}});this.contentBuffer.length;)this.push(this.contentBuffer.shift());this.currentFile=null},s.prototype.flush=function(){for(var t=this.bytesWritten,e=0;e<this.dirRecords.length;e++)this.push({data:this.dirRecords[e],meta:{percent:100}});var r=this.bytesWritten-t,i=function(t,e,r,i,n){var s=I.transformTo("string",n(i));return R.CENTRAL_DIRECTORY_END+"\0\0\0\0"+A(t,2)+A(t,2)+A(e,4)+A(r,4)+A(s.length,2)+s}(this.dirRecords.length,r,t,this.zipComment,this.encodeFileName);this.push({data:i,meta:{percent:100}})},s.prototype.prepareNextSource=function(){this.previous=this._sources.shift(),this.openedSource(this.previous.streamInfo),this.isPaused?this.previous.pause():this.previous.resume()},s.prototype.registerPrevious=function(t){this._sources.push(t);var e=this;return t.on("data",function(t){e.processChunk(t)}),t.on("end",function(){e.closedSource(e.previous.streamInfo),e._sources.length?e.prepareNextSource():e.end()}),t.on("error",function(t){e.error(t)}),this},s.prototype.resume=function(){return!!n.prototype.resume.call(this)&&(!this.previous&&this._sources.length?(this.prepareNextSource(),!0):this.previous||this._sources.length||this.generatedError?void 0:(this.end(),!0))},s.prototype.error=function(t){var e=this._sources;if(!n.prototype.error.call(this,t))return!1;for(var r=0;r<e.length;r++)try{e[r].error(t)}catch(t){}return!0},s.prototype.lock=function(){n.prototype.lock.call(this);for(var t=this._sources,e=0;e<t.length;e++)t[e].lock()},e.exports=s},{"../crc32":4,"../signature":23,"../stream/GenericWorker":28,"../utf8":31,"../utils":32}],9:[function(t,e,r){"use strict";var u=t("../compressions"),i=t("./ZipFileWorker");r.generateWorker=function(t,a,e){var o=new i(a.streamFiles,e,a.platform,a.encodeFileName),h=0;try{t.forEach(function(t,e){h++;var r=function(t,e){var r=t||e,i=u[r];if(!i)throw new Error(r+" is not a valid compression method !");return i}(e.options.compression,a.compression),i=e.options.compressionOptions||a.compressionOptions||{},n=e.dir,s=e.date;e._compressWorker(r,i).withStreamInfo("file",{name:t,dir:n,date:s,comment:e.comment||"",unixPermissions:e.unixPermissions,dosPermissions:e.dosPermissions}).pipe(o)}),o.entriesCount=h}catch(t){o.error(t)}return o}},{"../compressions":3,"./ZipFileWorker":8}],10:[function(t,e,r){"use strict";function i(){if(!(this instanceof i))return new i;if(arguments.length)throw new Error("The constructor with parameters has been removed in JSZip 3.0, please check the upgrade guide.");this.files={},this.comment=null,this.root="",this.clone=function(){var t=new i;for(var e in this)"function"!=typeof this[e]&&(t[e]=this[e]);return t}}(i.prototype=t("./object")).loadAsync=t("./load"),i.support=t("./support"),i.defaults=t("./defaults"),i.version="3.4.0",i.loadAsync=function(t,e){return(new i).loadAsync(t,e)},i.external=t("./external"),e.exports=i},{"./defaults":5,"./external":6,"./load":11,"./object":15,"./support":30}],11:[function(t,e,r){"use strict";var i=t("./utils"),n=t("./external"),o=t("./utf8"),h=(i=t("./utils"),t("./zipEntries")),s=t("./stream/Crc32Probe"),u=t("./nodejsUtils");function l(i){return new n.Promise(function(t,e){var r=i.decompressed.getContentWorker().pipe(new s);r.on("error",function(t){e(t)}).on("end",function(){r.streamInfo.crc32!==i.decompressed.crc32?e(new Error("Corrupted zip : CRC32 mismatch")):t()}).resume()})}e.exports=function(t,s){var a=this;return s=i.extend(s||{},{base64:!1,checkCRC32:!1,optimizedBinaryString:!1,createFolders:!1,decodeFileName:o.utf8decode}),u.isNode&&u.isStream(t)?n.Promise.reject(new Error("JSZip can't accept a stream when loading a zip file.")):i.prepareContent("the loaded zip file",t,!0,s.optimizedBinaryString,s.base64).then(function(t){var e=new h(s);return e.load(t),e}).then(function(t){var e=[n.Promise.resolve(t)],r=t.files;if(s.checkCRC32)for(var i=0;i<r.length;i++)e.push(l(r[i]));return n.Promise.all(e)}).then(function(t){for(var e=t.shift(),r=e.files,i=0;i<r.length;i++){var n=r[i];a.file(n.fileNameStr,n.decompressed,{binary:!0,optimizedBinaryString:!0,date:n.date,dir:n.dir,comment:n.fileCommentStr.length?n.fileCommentStr:null,unixPermissions:n.unixPermissions,dosPermissions:n.dosPermissions,createFolders:s.createFolders})}return e.zipComment.length&&(a.comment=e.zipComment),a})}},{"./external":6,"./nodejsUtils":14,"./stream/Crc32Probe":25,"./utf8":31,"./utils":32,"./zipEntries":33}],12:[function(t,e,r){"use strict";var i=t("../utils"),n=t("../stream/GenericWorker");function s(t,e){n.call(this,"Nodejs stream input adapter for "+t),this._upstreamEnded=!1,this._bindStream(e)}i.inherits(s,n),s.prototype._bindStream=function(t){var e=this;(this._stream=t).pause(),t.on("data",function(t){e.push({data:t,meta:{percent:0}})}).on("error",function(t){e.isPaused?this.generatedError=t:e.error(t)}).on("end",function(){e.isPaused?e._upstreamEnded=!0:e.end()})},s.prototype.pause=function(){return!!n.prototype.pause.call(this)&&(this._stream.pause(),!0)},s.prototype.resume=function(){return!!n.prototype.resume.call(this)&&(this._upstreamEnded?this.end():this._stream.resume(),!0)},e.exports=s},{"../stream/GenericWorker":28,"../utils":32}],13:[function(t,e,r){"use strict";var n=t("readable-stream").Readable;function i(t,e,r){n.call(this,e),this._helper=t;var i=this;t.on("data",function(t,e){i.push(t)||i._helper.pause(),r&&r(e)}).on("error",function(t){i.emit("error",t)}).on("end",function(){i.push(null)})}t("../utils").inherits(i,n),i.prototype._read=function(){this._helper.resume()},e.exports=i},{"../utils":32,"readable-stream":16}],14:[function(t,e,r){"use strict";e.exports={isNode:"undefined"!=typeof Buffer,newBufferFrom:function(t,e){if(Buffer.from&&Buffer.from!==Uint8Array.from)return Buffer.from(t,e);if("number"==typeof t)throw new Error('The "data" argument must not be a number');return new Buffer(t,e)},allocBuffer:function(t){if(Buffer.alloc)return Buffer.alloc(t);var e=new Buffer(t);return e.fill(0),e},isBuffer:function(t){return Buffer.isBuffer(t)},isStream:function(t){return t&&"function"==typeof t.on&&"function"==typeof t.pause&&"function"==typeof t.resume}}},{}],15:[function(t,e,r){"use strict";function s(t,e,r){var i,n=u.getTypeOf(e),s=u.extend(r||{},f);s.date=s.date||new Date,null!==s.compression&&(s.compression=s.compression.toUpperCase()),"string"==typeof s.unixPermissions&&(s.unixPermissions=parseInt(s.unixPermissions,8)),s.unixPermissions&&16384&s.unixPermissions&&(s.dir=!0),s.dosPermissions&&16&s.dosPermissions&&(s.dir=!0),s.dir&&(t=g(t)),s.createFolders&&(i=_(t))&&b.call(this,i,!0);var a="string"===n&&!1===s.binary&&!1===s.base64;r&&void 0!==r.binary||(s.binary=!a),(e instanceof d&&0===e.uncompressedSize||s.dir||!e||0===e.length)&&(s.base64=!1,s.binary=!0,e="",s.compression="STORE",n="string");var o=null;o=e instanceof d||e instanceof l?e:p.isNode&&p.isStream(e)?new m(t,e):u.prepareContent(t,e,s.binary,s.optimizedBinaryString,s.base64);var h=new c(t,o,s);this.files[t]=h}var n=t("./utf8"),u=t("./utils"),l=t("./stream/GenericWorker"),a=t("./stream/StreamHelper"),f=t("./defaults"),d=t("./compressedObject"),c=t("./zipObject"),o=t("./generate"),p=t("./nodejsUtils"),m=t("./nodejs/NodejsStreamInputAdapter"),_=function(t){"/"===t.slice(-1)&&(t=t.substring(0,t.length-1));var e=t.lastIndexOf("/");return 0<e?t.substring(0,e):""},g=function(t){return"/"!==t.slice(-1)&&(t+="/"),t},b=function(t,e){return e=void 0!==e?e:f.createFolders,t=g(t),this.files[t]||s.call(this,t,null,{dir:!0,createFolders:e}),this.files[t]};function h(t){return"[object RegExp]"===Object.prototype.toString.call(t)}var i={load:function(){throw new Error("This method has been removed in JSZip 3.0, please check the upgrade guide.")},forEach:function(t){var e,r,i;for(e in this.files)this.files.hasOwnProperty(e)&&(i=this.files[e],(r=e.slice(this.root.length,e.length))&&e.slice(0,this.root.length)===this.root&&t(r,i))},filter:function(r){var i=[];return this.forEach(function(t,e){r(t,e)&&i.push(e)}),i},file:function(t,e,r){if(1!==arguments.length)return t=this.root+t,s.call(this,t,e,r),this;if(h(t)){var i=t;return this.filter(function(t,e){return!e.dir&&i.test(t)})}var n=this.files[this.root+t];return n&&!n.dir?n:null},folder:function(r){if(!r)return this;if(h(r))return this.filter(function(t,e){return e.dir&&r.test(t)});var t=this.root+r,e=b.call(this,t),i=this.clone();return i.root=e.name,i},remove:function(r){r=this.root+r;var t=this.files[r];if(t||("/"!==r.slice(-1)&&(r+="/"),t=this.files[r]),t&&!t.dir)delete this.files[r];else for(var e=this.filter(function(t,e){return e.name.slice(0,r.length)===r}),i=0;i<e.length;i++)delete this.files[e[i].name];return this},generate:function(t){throw new Error("This method has been removed in JSZip 3.0, please check the upgrade guide.")},generateInternalStream:function(t){var e,r={};try{if((r=u.extend(t||{},{streamFiles:!1,compression:"STORE",compressionOptions:null,type:"",platform:"DOS",comment:null,mimeType:"application/zip",encodeFileName:n.utf8encode})).type=r.type.toLowerCase(),r.compression=r.compression.toUpperCase(),"binarystring"===r.type&&(r.type="string"),!r.type)throw new Error("No output type specified.");u.checkSupport(r.type),"darwin"!==r.platform&&"freebsd"!==r.platform&&"linux"!==r.platform&&"sunos"!==r.platform||(r.platform="UNIX"),"win32"===r.platform&&(r.platform="DOS");var i=r.comment||this.comment||"";e=o.generateWorker(this,r,i)}catch(t){(e=new l("error")).error(t)}return new a(e,r.type||"string",r.mimeType)},generateAsync:function(t,e){return this.generateInternalStream(t).accumulate(e)},generateNodeStream:function(t,e){return(t=t||{}).type||(t.type="nodebuffer"),this.generateInternalStream(t).toNodejsStream(e)}};e.exports=i},{"./compressedObject":2,"./defaults":5,"./generate":9,"./nodejs/NodejsStreamInputAdapter":12,"./nodejsUtils":14,"./stream/GenericWorker":28,"./stream/StreamHelper":29,"./utf8":31,"./utils":32,"./zipObject":35}],16:[function(t,e,r){e.exports=t("stream")},{stream:void 0}],17:[function(t,e,r){"use strict";var i=t("./DataReader");function n(t){i.call(this,t);for(var e=0;e<this.data.length;e++)t[e]=255&t[e]}t("../utils").inherits(n,i),n.prototype.byteAt=function(t){return this.data[this.zero+t]},n.prototype.lastIndexOfSignature=function(t){for(var e=t.charCodeAt(0),r=t.charCodeAt(1),i=t.charCodeAt(2),n=t.charCodeAt(3),s=this.length-4;0<=s;--s)if(this.data[s]===e&&this.data[s+1]===r&&this.data[s+2]===i&&this.data[s+3]===n)return s-this.zero;return-1},n.prototype.readAndCheckSignature=function(t){var e=t.charCodeAt(0),r=t.charCodeAt(1),i=t.charCodeAt(2),n=t.charCodeAt(3),s=this.readData(4);return e===s[0]&&r===s[1]&&i===s[2]&&n===s[3]},n.prototype.readData=function(t){if(this.checkOffset(t),0===t)return[];var e=this.data.slice(this.zero+this.index,this.zero+this.index+t);return this.index+=t,e},e.exports=n},{"../utils":32,"./DataReader":18}],18:[function(t,e,r){"use strict";var i=t("../utils");function n(t){this.data=t,this.length=t.length,this.index=0,this.zero=0}n.prototype={checkOffset:function(t){this.checkIndex(this.index+t)},checkIndex:function(t){if(this.length<this.zero+t||t<0)throw new Error("End of data reached (data length = "+this.length+", asked index = "+t+"). Corrupted zip ?")},setIndex:function(t){this.checkIndex(t),this.index=t},skip:function(t){this.setIndex(this.index+t)},byteAt:function(t){},readInt:function(t){var e,r=0;for(this.checkOffset(t),e=this.index+t-1;e>=this.index;e--)r=(r<<8)+this.byteAt(e);return this.index+=t,r},readString:function(t){return i.transformTo("string",this.readData(t))},readData:function(t){},lastIndexOfSignature:function(t){},readAndCheckSignature:function(t){},readDate:function(){var t=this.readInt(4);return new Date(Date.UTC(1980+(t>>25&127),(t>>21&15)-1,t>>16&31,t>>11&31,t>>5&63,(31&t)<<1))}},e.exports=n},{"../utils":32}],19:[function(t,e,r){"use strict";var i=t("./Uint8ArrayReader");function n(t){i.call(this,t)}t("../utils").inherits(n,i),n.prototype.readData=function(t){this.checkOffset(t);var e=this.data.slice(this.zero+this.index,this.zero+this.index+t);return this.index+=t,e},e.exports=n},{"../utils":32,"./Uint8ArrayReader":21}],20:[function(t,e,r){"use strict";var i=t("./DataReader");function n(t){i.call(this,t)}t("../utils").inherits(n,i),n.prototype.byteAt=function(t){return this.data.charCodeAt(this.zero+t)},n.prototype.lastIndexOfSignature=function(t){return this.data.lastIndexOf(t)-this.zero},n.prototype.readAndCheckSignature=function(t){return t===this.readData(4)},n.prototype.readData=function(t){this.checkOffset(t);var e=this.data.slice(this.zero+this.index,this.zero+this.index+t);return this.index+=t,e},e.exports=n},{"../utils":32,"./DataReader":18}],21:[function(t,e,r){"use strict";var i=t("./ArrayReader");function n(t){i.call(this,t)}t("../utils").inherits(n,i),n.prototype.readData=function(t){if(this.checkOffset(t),0===t)return new Uint8Array(0);var e=this.data.subarray(this.zero+this.index,this.zero+this.index+t);return this.index+=t,e},e.exports=n},{"../utils":32,"./ArrayReader":17}],22:[function(t,e,r){"use strict";var i=t("../utils"),n=t("../support"),s=t("./ArrayReader"),a=t("./StringReader"),o=t("./NodeBufferReader"),h=t("./Uint8ArrayReader");e.exports=function(t){var e=i.getTypeOf(t);return i.checkSupport(e),"string"!==e||n.uint8array?"nodebuffer"===e?new o(t):n.uint8array?new h(i.transformTo("uint8array",t)):new s(i.transformTo("array",t)):new a(t)}},{"../support":30,"../utils":32,"./ArrayReader":17,"./NodeBufferReader":19,"./StringReader":20,"./Uint8ArrayReader":21}],23:[function(t,e,r){"use strict";r.LOCAL_FILE_HEADER="PK",r.CENTRAL_FILE_HEADER="PK",r.CENTRAL_DIRECTORY_END="PK",r.ZIP64_CENTRAL_DIRECTORY_LOCATOR="PK",r.ZIP64_CENTRAL_DIRECTORY_END="PK",r.DATA_DESCRIPTOR="PK\b"},{}],24:[function(t,e,r){"use strict";var i=t("./GenericWorker"),n=t("../utils");function s(t){i.call(this,"ConvertWorker to "+t),this.destType=t}n.inherits(s,i),s.prototype.processChunk=function(t){this.push({data:n.transformTo(this.destType,t.data),meta:t.meta})},e.exports=s},{"../utils":32,"./GenericWorker":28}],25:[function(t,e,r){"use strict";var i=t("./GenericWorker"),n=t("../crc32");function s(){i.call(this,"Crc32Probe"),this.withStreamInfo("crc32",0)}t("../utils").inherits(s,i),s.prototype.processChunk=function(t){this.streamInfo.crc32=n(t.data,this.streamInfo.crc32||0),this.push(t)},e.exports=s},{"../crc32":4,"../utils":32,"./GenericWorker":28}],26:[function(t,e,r){"use strict";var i=t("../utils"),n=t("./GenericWorker");function s(t){n.call(this,"DataLengthProbe for "+t),this.propName=t,this.withStreamInfo(t,0)}i.inherits(s,n),s.prototype.processChunk=function(t){if(t){var e=this.streamInfo[this.propName]||0;this.streamInfo[this.propName]=e+t.data.length}n.prototype.processChunk.call(this,t)},e.exports=s},{"../utils":32,"./GenericWorker":28}],27:[function(t,e,r){"use strict";var i=t("../utils"),n=t("./GenericWorker");function s(t){n.call(this,"DataWorker");var e=this;this.dataIsReady=!1,this.index=0,this.max=0,this.data=null,this.type="",this._tickScheduled=!1,t.then(function(t){e.dataIsReady=!0,e.data=t,e.max=t&&t.length||0,e.type=i.getTypeOf(t),e.isPaused||e._tickAndRepeat()},function(t){e.error(t)})}i.inherits(s,n),s.prototype.cleanUp=function(){n.prototype.cleanUp.call(this),this.data=null},s.prototype.resume=function(){return!!n.prototype.resume.call(this)&&(!this._tickScheduled&&this.dataIsReady&&(this._tickScheduled=!0,i.delay(this._tickAndRepeat,[],this)),!0)},s.prototype._tickAndRepeat=function(){this._tickScheduled=!1,this.isPaused||this.isFinished||(this._tick(),this.isFinished||(i.delay(this._tickAndRepeat,[],this),this._tickScheduled=!0))},s.prototype._tick=function(){if(this.isPaused||this.isFinished)return!1;var t=null,e=Math.min(this.max,this.index+16384);if(this.index>=this.max)return this.end();switch(this.type){case"string":t=this.data.substring(this.index,e);break;case"uint8array":t=this.data.subarray(this.index,e);break;case"array":case"nodebuffer":t=this.data.slice(this.index,e)}return this.index=e,this.push({data:t,meta:{percent:this.max?this.index/this.max*100:0}})},e.exports=s},{"../utils":32,"./GenericWorker":28}],28:[function(t,e,r){"use strict";function i(t){this.name=t||"default",this.streamInfo={},this.generatedError=null,this.extraStreamInfo={},this.isPaused=!0,this.isFinished=!1,this.isLocked=!1,this._listeners={data:[],end:[],error:[]},this.previous=null}i.prototype={push:function(t){this.emit("data",t)},end:function(){if(this.isFinished)return!1;this.flush();try{this.emit("end"),this.cleanUp(),this.isFinished=!0}catch(t){this.emit("error",t)}return!0},error:function(t){return!this.isFinished&&(this.isPaused?this.generatedError=t:(this.isFinished=!0,this.emit("error",t),this.previous&&this.previous.error(t),this.cleanUp()),!0)},on:function(t,e){return this._listeners[t].push(e),this},cleanUp:function(){this.streamInfo=this.generatedError=this.extraStreamInfo=null,this._listeners=[]},emit:function(t,e){if(this._listeners[t])for(var r=0;r<this._listeners[t].length;r++)this._listeners[t][r].call(this,e)},pipe:function(t){return t.registerPrevious(this)},registerPrevious:function(t){if(this.isLocked)throw new Error("The stream '"+this+"' has already been used.");this.streamInfo=t.streamInfo,this.mergeStreamInfo(),this.previous=t;var e=this;return t.on("data",function(t){e.processChunk(t)}),t.on("end",function(){e.end()}),t.on("error",function(t){e.error(t)}),this},pause:function(){return!this.isPaused&&!this.isFinished&&(this.isPaused=!0,this.previous&&this.previous.pause(),!0)},resume:function(){if(!this.isPaused||this.isFinished)return!1;var t=this.isPaused=!1;return this.generatedError&&(this.error(this.generatedError),t=!0),this.previous&&this.previous.resume(),!t},flush:function(){},processChunk:function(t){this.push(t)},withStreamInfo:function(t,e){return this.extraStreamInfo[t]=e,this.mergeStreamInfo(),this},mergeStreamInfo:function(){for(var t in this.extraStreamInfo)this.extraStreamInfo.hasOwnProperty(t)&&(this.streamInfo[t]=this.extraStreamInfo[t])},lock:function(){if(this.isLocked)throw new Error("The stream '"+this+"' has already been used.");this.isLocked=!0,this.previous&&this.previous.lock()},toString:function(){var t="Worker "+this.name;return this.previous?this.previous+" -> "+t:t}},e.exports=i},{}],29:[function(t,e,r){"use strict";var h=t("../utils"),n=t("./ConvertWorker"),s=t("./GenericWorker"),u=t("../base64"),i=t("../support"),a=t("../external"),o=null;if(i.nodestream)try{o=t("../nodejs/NodejsStreamOutputAdapter")}catch(t){}function l(t,o){return new a.Promise(function(e,r){var i=[],n=t._internalType,s=t._outputType,a=t._mimeType;t.on("data",function(t,e){i.push(t),o&&o(e)}).on("error",function(t){i=[],r(t)}).on("end",function(){try{var t=function(t,e,r){switch(t){case"blob":return h.newBlob(h.transformTo("arraybuffer",e),r);case"base64":return u.encode(e);default:return h.transformTo(t,e)}}(s,function(t,e){var r,i=0,n=null,s=0;for(r=0;r<e.length;r++)s+=e[r].length;switch(t){case"string":return e.join("");case"array":return Array.prototype.concat.apply([],e);case"uint8array":for(n=new Uint8Array(s),r=0;r<e.length;r++)n.set(e[r],i),i+=e[r].length;return n;case"nodebuffer":return Buffer.concat(e);default:throw new Error("concat : unsupported type '"+t+"'")}}(n,i),a);e(t)}catch(t){r(t)}i=[]}).resume()})}function f(t,e,r){var i=e;switch(e){case"blob":case"arraybuffer":i="uint8array";break;case"base64":i="string"}try{this._internalType=i,this._outputType=e,this._mimeType=r,h.checkSupport(i),this._worker=t.pipe(new n(i)),t.lock()}catch(t){this._worker=new s("error"),this._worker.error(t)}}f.prototype={accumulate:function(t){return l(this,t)},on:function(t,e){var r=this;return"data"===t?this._worker.on(t,function(t){e.call(r,t.data,t.meta)}):this._worker.on(t,function(){h.delay(e,arguments,r)}),this},resume:function(){return h.delay(this._worker.resume,[],this._worker),this},pause:function(){return this._worker.pause(),this},toNodejsStream:function(t){if(h.checkSupport("nodestream"),"nodebuffer"!==this._outputType)throw new Error(this._outputType+" is not supported by this method");return new o(this,{objectMode:"nodebuffer"!==this._outputType},t)}},e.exports=f},{"../base64":1,"../external":6,"../nodejs/NodejsStreamOutputAdapter":13,"../support":30,"../utils":32,"./ConvertWorker":24,"./GenericWorker":28}],30:[function(t,e,r){"use strict";if(r.base64=!0,r.array=!0,r.string=!0,r.arraybuffer="undefined"!=typeof ArrayBuffer&&"undefined"!=typeof Uint8Array,r.nodebuffer="undefined"!=typeof Buffer,r.uint8array="undefined"!=typeof Uint8Array,"undefined"==typeof ArrayBuffer)r.blob=!1;else{var i=new ArrayBuffer(0);try{r.blob=0===new Blob([i],{type:"application/zip"}).size}catch(t){try{var n=new(self.BlobBuilder||self.WebKitBlobBuilder||self.MozBlobBuilder||self.MSBlobBuilder);n.append(i),r.blob=0===n.getBlob("application/zip").size}catch(t){r.blob=!1}}}try{r.nodestream=!!t("readable-stream").Readable}catch(t){r.nodestream=!1}},{"readable-stream":16}],31:[function(t,e,s){"use strict";for(var o=t("./utils"),h=t("./support"),r=t("./nodejsUtils"),i=t("./stream/GenericWorker"),u=new Array(256),n=0;n<256;n++)u[n]=252<=n?6:248<=n?5:240<=n?4:224<=n?3:192<=n?2:1;u[254]=u[254]=1;function a(){i.call(this,"utf-8 decode"),this.leftOver=null}function l(){i.call(this,"utf-8 encode")}s.utf8encode=function(t){return h.nodebuffer?r.newBufferFrom(t,"utf-8"):function(t){var e,r,i,n,s,a=t.length,o=0;for(n=0;n<a;n++)55296==(64512&(r=t.charCodeAt(n)))&&n+1<a&&56320==(64512&(i=t.charCodeAt(n+1)))&&(r=65536+(r-55296<<10)+(i-56320),n++),o+=r<128?1:r<2048?2:r<65536?3:4;for(e=h.uint8array?new Uint8Array(o):new Array(o),n=s=0;s<o;n++)55296==(64512&(r=t.charCodeAt(n)))&&n+1<a&&56320==(64512&(i=t.charCodeAt(n+1)))&&(r=65536+(r-55296<<10)+(i-56320),n++),r<128?e[s++]=r:(r<2048?e[s++]=192|r>>>6:(r<65536?e[s++]=224|r>>>12:(e[s++]=240|r>>>18,e[s++]=128|r>>>12&63),e[s++]=128|r>>>6&63),e[s++]=128|63&r);return e}(t)},s.utf8decode=function(t){return h.nodebuffer?o.transformTo("nodebuffer",t).toString("utf-8"):function(t){var e,r,i,n,s=t.length,a=new Array(2*s);for(e=r=0;e<s;)if((i=t[e++])<128)a[r++]=i;else if(4<(n=u[i]))a[r++]=65533,e+=n-1;else{for(i&=2===n?31:3===n?15:7;1<n&&e<s;)i=i<<6|63&t[e++],n--;1<n?a[r++]=65533:i<65536?a[r++]=i:(i-=65536,a[r++]=55296|i>>10&1023,a[r++]=56320|1023&i)}return a.length!==r&&(a.subarray?a=a.subarray(0,r):a.length=r),o.applyFromCharCode(a)}(t=o.transformTo(h.uint8array?"uint8array":"array",t))},o.inherits(a,i),a.prototype.processChunk=function(t){var e=o.transformTo(h.uint8array?"uint8array":"array",t.data);if(this.leftOver&&this.leftOver.length){if(h.uint8array){var r=e;(e=new Uint8Array(r.length+this.leftOver.length)).set(this.leftOver,0),e.set(r,this.leftOver.length)}else e=this.leftOver.concat(e);this.leftOver=null}var i=function(t,e){var r;for((e=e||t.length)>t.length&&(e=t.length),r=e-1;0<=r&&128==(192&t[r]);)r--;return r<0?e:0===r?e:r+u[t[r]]>e?r:e}(e),n=e;i!==e.length&&(h.uint8array?(n=e.subarray(0,i),this.leftOver=e.subarray(i,e.length)):(n=e.slice(0,i),this.leftOver=e.slice(i,e.length))),this.push({data:s.utf8decode(n),meta:t.meta})},a.prototype.flush=function(){this.leftOver&&this.leftOver.length&&(this.push({data:s.utf8decode(this.leftOver),meta:{}}),this.leftOver=null)},s.Utf8DecodeWorker=a,o.inherits(l,i),l.prototype.processChunk=function(t){this.push({data:s.utf8encode(t.data),meta:t.meta})},s.Utf8EncodeWorker=l},{"./nodejsUtils":14,"./stream/GenericWorker":28,"./support":30,"./utils":32}],32:[function(t,e,a){"use strict";var o=t("./support"),h=t("./base64"),r=t("./nodejsUtils"),i=t("set-immediate-shim"),u=t("./external");function n(t){return t}function l(t,e){for(var r=0;r<t.length;++r)e[r]=255&t.charCodeAt(r);return e}a.newBlob=function(e,r){a.checkSupport("blob");try{return new Blob([e],{type:r})}catch(t){try{var i=new(self.BlobBuilder||self.WebKitBlobBuilder||self.MozBlobBuilder||self.MSBlobBuilder);return i.append(e),i.getBlob(r)}catch(t){throw new Error("Bug : can't construct the Blob.")}}};var s={stringifyByChunk:function(t,e,r){var i=[],n=0,s=t.length;if(s<=r)return String.fromCharCode.apply(null,t);for(;n<s;)"array"===e||"nodebuffer"===e?i.push(String.fromCharCode.apply(null,t.slice(n,Math.min(n+r,s)))):i.push(String.fromCharCode.apply(null,t.subarray(n,Math.min(n+r,s)))),n+=r;return i.join("")},stringifyByChar:function(t){for(var e="",r=0;r<t.length;r++)e+=String.fromCharCode(t[r]);return e},applyCanBeUsed:{uint8array:function(){try{return o.uint8array&&1===String.fromCharCode.apply(null,new Uint8Array(1)).length}catch(t){return!1}}(),nodebuffer:function(){try{return o.nodebuffer&&1===String.fromCharCode.apply(null,r.allocBuffer(1)).length}catch(t){return!1}}()}};function f(t){var e=65536,r=a.getTypeOf(t),i=!0;if("uint8array"===r?i=s.applyCanBeUsed.uint8array:"nodebuffer"===r&&(i=s.applyCanBeUsed.nodebuffer),i)for(;1<e;)try{return s.stringifyByChunk(t,r,e)}catch(t){e=Math.floor(e/2)}return s.stringifyByChar(t)}function d(t,e){for(var r=0;r<t.length;r++)e[r]=t[r];return e}a.applyFromCharCode=f;var c={};c.string={string:n,array:function(t){return l(t,new Array(t.length))},arraybuffer:function(t){return c.string.uint8array(t).buffer},uint8array:function(t){return l(t,new Uint8Array(t.length))},nodebuffer:function(t){return l(t,r.allocBuffer(t.length))}},c.array={string:f,array:n,arraybuffer:function(t){return new Uint8Array(t).buffer},uint8array:function(t){return new Uint8Array(t)},nodebuffer:function(t){return r.newBufferFrom(t)}},c.arraybuffer={string:function(t){return f(new Uint8Array(t))},array:function(t){return d(new Uint8Array(t),new Array(t.byteLength))},arraybuffer:n,uint8array:function(t){return new Uint8Array(t)},nodebuffer:function(t){return r.newBufferFrom(new Uint8Array(t))}},c.uint8array={string:f,array:function(t){return d(t,new Array(t.length))},arraybuffer:function(t){return t.buffer},uint8array:n,nodebuffer:function(t){return r.newBufferFrom(t)}},c.nodebuffer={string:f,array:function(t){return d(t,new Array(t.length))},arraybuffer:function(t){return c.nodebuffer.uint8array(t).buffer},uint8array:function(t){return d(t,new Uint8Array(t.length))},nodebuffer:n},a.transformTo=function(t,e){if(e=e||"",!t)return e;a.checkSupport(t);var r=a.getTypeOf(e);return c[r][t](e)},a.getTypeOf=function(t){return"string"==typeof t?"string":"[object Array]"===Object.prototype.toString.call(t)?"array":o.nodebuffer&&r.isBuffer(t)?"nodebuffer":o.uint8array&&t instanceof Uint8Array?"uint8array":o.arraybuffer&&t instanceof ArrayBuffer?"arraybuffer":void 0},a.checkSupport=function(t){if(!o[t.toLowerCase()])throw new Error(t+" is not supported by this platform")},a.MAX_VALUE_16BITS=65535,a.MAX_VALUE_32BITS=-1,a.pretty=function(t){var e,r,i="";for(r=0;r<(t||"").length;r++)i+="\\x"+((e=t.charCodeAt(r))<16?"0":"")+e.toString(16).toUpperCase();return i},a.delay=function(t,e,r){i(function(){t.apply(r||null,e||[])})},a.inherits=function(t,e){function r(){}r.prototype=e.prototype,t.prototype=new r},a.extend=function(){var t,e,r={};for(t=0;t<arguments.length;t++)for(e in arguments[t])arguments[t].hasOwnProperty(e)&&void 0===r[e]&&(r[e]=arguments[t][e]);return r},a.prepareContent=function(r,t,i,n,s){return u.Promise.resolve(t).then(function(i){return o.blob&&(i instanceof Blob||-1!==["[object File]","[object Blob]"].indexOf(Object.prototype.toString.call(i)))&&"undefined"!=typeof FileReader?new u.Promise(function(e,r){var t=new FileReader;t.onload=function(t){e(t.target.result)},t.onerror=function(t){r(t.target.error)},t.readAsArrayBuffer(i)}):i}).then(function(t){var e=a.getTypeOf(t);return e?("arraybuffer"===e?t=a.transformTo("uint8array",t):"string"===e&&(s?t=h.decode(t):i&&!0!==n&&(t=function(t){return l(t,o.uint8array?new Uint8Array(t.length):new Array(t.length))}(t))),t):u.Promise.reject(new Error("Can't read the data of '"+r+"'. Is it in a supported JavaScript type (String, Blob, ArrayBuffer, etc) ?"))})}},{"./base64":1,"./external":6,"./nodejsUtils":14,"./support":30,"set-immediate-shim":54}],33:[function(t,e,r){"use strict";var i=t("./reader/readerFor"),n=t("./utils"),s=t("./signature"),a=t("./zipEntry"),o=(t("./utf8"),t("./support"));function h(t){this.files=[],this.loadOptions=t}h.prototype={checkSignature:function(t){if(!this.reader.readAndCheckSignature(t)){this.reader.index-=4;var e=this.reader.readString(4);throw new Error("Corrupted zip or bug: unexpected signature ("+n.pretty(e)+", expected "+n.pretty(t)+")")}},isSignature:function(t,e){var r=this.reader.index;this.reader.setIndex(t);var i=this.reader.readString(4)===e;return this.reader.setIndex(r),i},readBlockEndOfCentral:function(){this.diskNumber=this.reader.readInt(2),this.diskWithCentralDirStart=this.reader.readInt(2),this.centralDirRecordsOnThisDisk=this.reader.readInt(2),this.centralDirRecords=this.reader.readInt(2),this.centralDirSize=this.reader.readInt(4),this.centralDirOffset=this.reader.readInt(4),this.zipCommentLength=this.reader.readInt(2);var t=this.reader.readData(this.zipCommentLength),e=o.uint8array?"uint8array":"array",r=n.transformTo(e,t);this.zipComment=this.loadOptions.decodeFileName(r)},readBlockZip64EndOfCentral:function(){this.zip64EndOfCentralSize=this.reader.readInt(8),this.reader.skip(4),this.diskNumber=this.reader.readInt(4),this.diskWithCentralDirStart=this.reader.readInt(4),this.centralDirRecordsOnThisDisk=this.reader.readInt(8),this.centralDirRecords=this.reader.readInt(8),this.centralDirSize=this.reader.readInt(8),this.centralDirOffset=this.reader.readInt(8),this.zip64ExtensibleData={};for(var t,e,r,i=this.zip64EndOfCentralSize-44;0<i;)t=this.reader.readInt(2),e=this.reader.readInt(4),r=this.reader.readData(e),this.zip64ExtensibleData[t]={id:t,length:e,value:r}},readBlockZip64EndOfCentralLocator:function(){if(this.diskWithZip64CentralDirStart=this.reader.readInt(4),this.relativeOffsetEndOfZip64CentralDir=this.reader.readInt(8),this.disksCount=this.reader.readInt(4),1<this.disksCount)throw new Error("Multi-volumes zip are not supported")},readLocalFiles:function(){var t,e;for(t=0;t<this.files.length;t++)e=this.files[t],this.reader.setIndex(e.localHeaderOffset),this.checkSignature(s.LOCAL_FILE_HEADER),e.readLocalPart(this.reader),e.handleUTF8(),e.processAttributes()},readCentralDir:function(){var t;for(this.reader.setIndex(this.centralDirOffset);this.reader.readAndCheckSignature(s.CENTRAL_FILE_HEADER);)(t=new a({zip64:this.zip64},this.loadOptions)).readCentralPart(this.reader),this.files.push(t);if(this.centralDirRecords!==this.files.length&&0!==this.centralDirRecords&&0===this.files.length)throw new Error("Corrupted zip or bug: expected "+this.centralDirRecords+" records in central dir, got "+this.files.length)},readEndOfCentral:function(){var t=this.reader.lastIndexOfSignature(s.CENTRAL_DIRECTORY_END);if(t<0)throw!this.isSignature(0,s.LOCAL_FILE_HEADER)?new Error("Can't find end of central directory : is this a zip file ? If it is, see https://stuk.github.io/jszip/documentation/howto/read_zip.html"):new Error("Corrupted zip: can't find end of central directory");this.reader.setIndex(t);var e=t;if(this.checkSignature(s.CENTRAL_DIRECTORY_END),this.readBlockEndOfCentral(),this.diskNumber===n.MAX_VALUE_16BITS||this.diskWithCentralDirStart===n.MAX_VALUE_16BITS||this.centralDirRecordsOnThisDisk===n.MAX_VALUE_16BITS||this.centralDirRecords===n.MAX_VALUE_16BITS||this.centralDirSize===n.MAX_VALUE_32BITS||this.centralDirOffset===n.MAX_VALUE_32BITS){if(this.zip64=!0,(t=this.reader.lastIndexOfSignature(s.ZIP64_CENTRAL_DIRECTORY_LOCATOR))<0)throw new Error("Corrupted zip: can't find the ZIP64 end of central directory locator");if(this.reader.setIndex(t),this.checkSignature(s.ZIP64_CENTRAL_DIRECTORY_LOCATOR),this.readBlockZip64EndOfCentralLocator(),!this.isSignature(this.relativeOffsetEndOfZip64CentralDir,s.ZIP64_CENTRAL_DIRECTORY_END)&&(this.relativeOffsetEndOfZip64CentralDir=this.reader.lastIndexOfSignature(s.ZIP64_CENTRAL_DIRECTORY_END),this.relativeOffsetEndOfZip64CentralDir<0))throw new Error("Corrupted zip: can't find the ZIP64 end of central directory");this.reader.setIndex(this.relativeOffsetEndOfZip64CentralDir),this.checkSignature(s.ZIP64_CENTRAL_DIRECTORY_END),this.readBlockZip64EndOfCentral()}var r=this.centralDirOffset+this.centralDirSize;this.zip64&&(r+=20,r+=12+this.zip64EndOfCentralSize);var i=e-r;if(0<i)this.isSignature(e,s.CENTRAL_FILE_HEADER)||(this.reader.zero=i);else if(i<0)throw new Error("Corrupted zip: missing "+Math.abs(i)+" bytes.")},prepareReader:function(t){this.reader=i(t)},load:function(t){this.prepareReader(t),this.readEndOfCentral(),this.readCentralDir(),this.readLocalFiles()}},e.exports=h},{"./reader/readerFor":22,"./signature":23,"./support":30,"./utf8":31,"./utils":32,"./zipEntry":34}],34:[function(t,e,r){"use strict";var i=t("./reader/readerFor"),s=t("./utils"),n=t("./compressedObject"),a=t("./crc32"),o=t("./utf8"),h=t("./compressions"),u=t("./support");function l(t,e){this.options=t,this.loadOptions=e}l.prototype={isEncrypted:function(){return 1==(1&this.bitFlag)},useUTF8:function(){return 2048==(2048&this.bitFlag)},readLocalPart:function(t){var e,r;if(t.skip(22),this.fileNameLength=t.readInt(2),r=t.readInt(2),this.fileName=t.readData(this.fileNameLength),t.skip(r),-1===this.compressedSize||-1===this.uncompressedSize)throw new Error("Bug or corrupted zip : didn't get enough information from the central directory (compressedSize === -1 || uncompressedSize === -1)");if(null===(e=function(t){for(var e in h)if(h.hasOwnProperty(e)&&h[e].magic===t)return h[e];return null}(this.compressionMethod)))throw new Error("Corrupted zip : compression "+s.pretty(this.compressionMethod)+" unknown (inner file : "+s.transformTo("string",this.fileName)+")");this.decompressed=new n(this.compressedSize,this.uncompressedSize,this.crc32,e,t.readData(this.compressedSize))},readCentralPart:function(t){this.versionMadeBy=t.readInt(2),t.skip(2),this.bitFlag=t.readInt(2),this.compressionMethod=t.readString(2),this.date=t.readDate(),this.crc32=t.readInt(4),this.compressedSize=t.readInt(4),this.uncompressedSize=t.readInt(4);var e=t.readInt(2);if(this.extraFieldsLength=t.readInt(2),this.fileCommentLength=t.readInt(2),this.diskNumberStart=t.readInt(2),this.internalFileAttributes=t.readInt(2),this.externalFileAttributes=t.readInt(4),this.localHeaderOffset=t.readInt(4),this.isEncrypted())throw new Error("Encrypted zip are not supported");t.skip(e),this.readExtraFields(t),this.parseZIP64ExtraField(t),this.fileComment=t.readData(this.fileCommentLength)},processAttributes:function(){this.unixPermissions=null,this.dosPermissions=null;var t=this.versionMadeBy>>8;this.dir=!!(16&this.externalFileAttributes),0==t&&(this.dosPermissions=63&this.externalFileAttributes),3==t&&(this.unixPermissions=this.externalFileAttributes>>16&65535),this.dir||"/"!==this.fileNameStr.slice(-1)||(this.dir=!0)},parseZIP64ExtraField:function(t){if(this.extraFields[1]){var e=i(this.extraFields[1].value);this.uncompressedSize===s.MAX_VALUE_32BITS&&(this.uncompressedSize=e.readInt(8)),this.compressedSize===s.MAX_VALUE_32BITS&&(this.compressedSize=e.readInt(8)),this.localHeaderOffset===s.MAX_VALUE_32BITS&&(this.localHeaderOffset=e.readInt(8)),this.diskNumberStart===s.MAX_VALUE_32BITS&&(this.diskNumberStart=e.readInt(4))}},readExtraFields:function(t){var e,r,i,n=t.index+this.extraFieldsLength;for(this.extraFields||(this.extraFields={});t.index<n;)e=t.readInt(2),r=t.readInt(2),i=t.readData(r),this.extraFields[e]={id:e,length:r,value:i}},handleUTF8:function(){var t=u.uint8array?"uint8array":"array";if(this.useUTF8())this.fileNameStr=o.utf8decode(this.fileName),this.fileCommentStr=o.utf8decode(this.fileComment);else{var e=this.findExtraFieldUnicodePath();if(null!==e)this.fileNameStr=e;else{var r=s.transformTo(t,this.fileName);this.fileNameStr=this.loadOptions.decodeFileName(r)}var i=this.findExtraFieldUnicodeComment();if(null!==i)this.fileCommentStr=i;else{var n=s.transformTo(t,this.fileComment);this.fileCommentStr=this.loadOptions.decodeFileName(n)}}},findExtraFieldUnicodePath:function(){var t=this.extraFields[28789];if(t){var e=i(t.value);return 1!==e.readInt(1)?null:a(this.fileName)!==e.readInt(4)?null:o.utf8decode(e.readData(t.length-5))}return null},findExtraFieldUnicodeComment:function(){var t=this.extraFields[25461];if(t){var e=i(t.value);return 1!==e.readInt(1)?null:a(this.fileComment)!==e.readInt(4)?null:o.utf8decode(e.readData(t.length-5))}return null}},e.exports=l},{"./compressedObject":2,"./compressions":3,"./crc32":4,"./reader/readerFor":22,"./support":30,"./utf8":31,"./utils":32}],35:[function(t,e,r){"use strict";function i(t,e,r){this.name=t,this.dir=r.dir,this.date=r.date,this.comment=r.comment,this.unixPermissions=r.unixPermissions,this.dosPermissions=r.dosPermissions,this._data=e,this._dataBinary=r.binary,this.options={compression:r.compression,compressionOptions:r.compressionOptions}}var s=t("./stream/StreamHelper"),n=t("./stream/DataWorker"),a=t("./utf8"),o=t("./compressedObject"),h=t("./stream/GenericWorker");i.prototype={internalStream:function(t){var e=null,r="string";try{if(!t)throw new Error("No output type specified.");var i="string"===(r=t.toLowerCase())||"text"===r;"binarystring"!==r&&"text"!==r||(r="string"),e=this._decompressWorker();var n=!this._dataBinary;n&&!i&&(e=e.pipe(new a.Utf8EncodeWorker)),!n&&i&&(e=e.pipe(new a.Utf8DecodeWorker))}catch(t){(e=new h("error")).error(t)}return new s(e,r,"")},async:function(t,e){return this.internalStream(t).accumulate(e)},nodeStream:function(t,e){return this.internalStream(t||"nodebuffer").toNodejsStream(e)},_compressWorker:function(t,e){if(this._data instanceof o&&this._data.compression.magic===t.magic)return this._data.getCompressedWorker();var r=this._decompressWorker();return this._dataBinary||(r=r.pipe(new a.Utf8EncodeWorker)),o.createWorkerFrom(r,t,e)},_decompressWorker:function(){return this._data instanceof o?this._data.getContentWorker():this._data instanceof h?this._data:new n(this._data)}};for(var u=["asText","asBinary","asNodeBuffer","asUint8Array","asArrayBuffer"],l=function(){throw new Error("This method has been removed in JSZip 3.0, please check the upgrade guide.")},f=0;f<u.length;f++)i.prototype[u[f]]=l;e.exports=i},{"./compressedObject":2,"./stream/DataWorker":27,"./stream/GenericWorker":28,"./stream/StreamHelper":29,"./utf8":31}],36:[function(t,l,e){(function(e){"use strict";var r,i,t=e.MutationObserver||e.WebKitMutationObserver;if(t){var n=0,s=new t(u),a=e.document.createTextNode("");s.observe(a,{characterData:!0}),r=function(){a.data=n=++n%2}}else if(e.setImmediate||void 0===e.MessageChannel)r="document"in e&&"onreadystatechange"in e.document.createElement("script")?function(){var t=e.document.createElement("script");t.onreadystatechange=function(){u(),t.onreadystatechange=null,t.parentNode.removeChild(t),t=null},e.document.documentElement.appendChild(t)}:function(){setTimeout(u,0)};else{var o=new e.MessageChannel;o.port1.onmessage=u,r=function(){o.port2.postMessage(0)}}var h=[];function u(){var t,e;i=!0;for(var r=h.length;r;){for(e=h,h=[],t=-1;++t<r;)e[t]();r=h.length}i=!1}l.exports=function(t){1!==h.push(t)||i||r()}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],37:[function(t,e,r){"use strict";var n=t("immediate");function u(){}var l={},s=["REJECTED"],a=["FULFILLED"],i=["PENDING"];function o(t){if("function"!=typeof t)throw new TypeError("resolver must be a function");this.state=i,this.queue=[],this.outcome=void 0,t!==u&&c(this,t)}function h(t,e,r){this.promise=t,"function"==typeof e&&(this.onFulfilled=e,this.callFulfilled=this.otherCallFulfilled),"function"==typeof r&&(this.onRejected=r,this.callRejected=this.otherCallRejected)}function f(e,r,i){n(function(){var t;try{t=r(i)}catch(t){return l.reject(e,t)}t===e?l.reject(e,new TypeError("Cannot resolve promise with itself")):l.resolve(e,t)})}function d(t){var e=t&&t.then;if(t&&("object"==typeof t||"function"==typeof t)&&"function"==typeof e)return function(){e.apply(t,arguments)}}function c(e,t){var r=!1;function i(t){r||(r=!0,l.reject(e,t))}function n(t){r||(r=!0,l.resolve(e,t))}var s=p(function(){t(n,i)});"error"===s.status&&i(s.value)}function p(t,e){var r={};try{r.value=t(e),r.status="success"}catch(t){r.status="error",r.value=t}return r}(e.exports=o).prototype.finally=function(e){if("function"!=typeof e)return this;var r=this.constructor;return this.then(function(t){return r.resolve(e()).then(function(){return t})},function(t){return r.resolve(e()).then(function(){throw t})})},o.prototype.catch=function(t){return this.then(null,t)},o.prototype.then=function(t,e){if("function"!=typeof t&&this.state===a||"function"!=typeof e&&this.state===s)return this;var r=new this.constructor(u);this.state!==i?f(r,this.state===a?t:e,this.outcome):this.queue.push(new h(r,t,e));return r},h.prototype.callFulfilled=function(t){l.resolve(this.promise,t)},h.prototype.otherCallFulfilled=function(t){f(this.promise,this.onFulfilled,t)},h.prototype.callRejected=function(t){l.reject(this.promise,t)},h.prototype.otherCallRejected=function(t){f(this.promise,this.onRejected,t)},l.resolve=function(t,e){var r=p(d,e);if("error"===r.status)return l.reject(t,r.value);var i=r.value;if(i)c(t,i);else{t.state=a,t.outcome=e;for(var n=-1,s=t.queue.length;++n<s;)t.queue[n].callFulfilled(e)}return t},l.reject=function(t,e){t.state=s,t.outcome=e;for(var r=-1,i=t.queue.length;++r<i;)t.queue[r].callRejected(e);return t},o.resolve=function(t){if(t instanceof this)return t;return l.resolve(new this(u),t)},o.reject=function(t){var e=new this(u);return l.reject(e,t)},o.all=function(t){var r=this;if("[object Array]"!==Object.prototype.toString.call(t))return this.reject(new TypeError("must be an array"));var i=t.length,n=!1;if(!i)return this.resolve([]);var s=new Array(i),a=0,e=-1,o=new this(u);for(;++e<i;)h(t[e],e);return o;function h(t,e){r.resolve(t).then(function(t){s[e]=t,++a!==i||n||(n=!0,l.resolve(o,s))},function(t){n||(n=!0,l.reject(o,t))})}},o.race=function(t){var e=this;if("[object Array]"!==Object.prototype.toString.call(t))return this.reject(new TypeError("must be an array"));var r=t.length,i=!1;if(!r)return this.resolve([]);var n=-1,s=new this(u);for(;++n<r;)a=t[n],e.resolve(a).then(function(t){i||(i=!0,l.resolve(s,t))},function(t){i||(i=!0,l.reject(s,t))});var a;return s}},{immediate:36}],38:[function(t,e,r){"use strict";var i={};(0,t("./lib/utils/common").assign)(i,t("./lib/deflate"),t("./lib/inflate"),t("./lib/zlib/constants")),e.exports=i},{"./lib/deflate":39,"./lib/inflate":40,"./lib/utils/common":41,"./lib/zlib/constants":44}],39:[function(t,e,r){"use strict";var a=t("./zlib/deflate"),o=t("./utils/common"),h=t("./utils/strings"),n=t("./zlib/messages"),s=t("./zlib/zstream"),u=Object.prototype.toString,l=0,f=-1,d=0,c=8;function p(t){if(!(this instanceof p))return new p(t);this.options=o.assign({level:f,method:c,chunkSize:16384,windowBits:15,memLevel:8,strategy:d,to:""},t||{});var e=this.options;e.raw&&0<e.windowBits?e.windowBits=-e.windowBits:e.gzip&&0<e.windowBits&&e.windowBits<16&&(e.windowBits+=16),this.err=0,this.msg="",this.ended=!1,this.chunks=[],this.strm=new s,this.strm.avail_out=0;var r=a.deflateInit2(this.strm,e.level,e.method,e.windowBits,e.memLevel,e.strategy);if(r!==l)throw new Error(n[r]);if(e.header&&a.deflateSetHeader(this.strm,e.header),e.dictionary){var i;if(i="string"==typeof e.dictionary?h.string2buf(e.dictionary):"[object ArrayBuffer]"===u.call(e.dictionary)?new Uint8Array(e.dictionary):e.dictionary,(r=a.deflateSetDictionary(this.strm,i))!==l)throw new Error(n[r]);this._dict_set=!0}}function i(t,e){var r=new p(e);if(r.push(t,!0),r.err)throw r.msg||n[r.err];return r.result}p.prototype.push=function(t,e){var r,i,n=this.strm,s=this.options.chunkSize;if(this.ended)return!1;i=e===~~e?e:!0===e?4:0,"string"==typeof t?n.input=h.string2buf(t):"[object ArrayBuffer]"===u.call(t)?n.input=new Uint8Array(t):n.input=t,n.next_in=0,n.avail_in=n.input.length;do{if(0===n.avail_out&&(n.output=new o.Buf8(s),n.next_out=0,n.avail_out=s),1!==(r=a.deflate(n,i))&&r!==l)return this.onEnd(r),!(this.ended=!0);0!==n.avail_out&&(0!==n.avail_in||4!==i&&2!==i)||("string"===this.options.to?this.onData(h.buf2binstring(o.shrinkBuf(n.output,n.next_out))):this.onData(o.shrinkBuf(n.output,n.next_out)))}while((0<n.avail_in||0===n.avail_out)&&1!==r);return 4===i?(r=a.deflateEnd(this.strm),this.onEnd(r),this.ended=!0,r===l):2!==i||(this.onEnd(l),!(n.avail_out=0))},p.prototype.onData=function(t){this.chunks.push(t)},p.prototype.onEnd=function(t){t===l&&("string"===this.options.to?this.result=this.chunks.join(""):this.result=o.flattenChunks(this.chunks)),this.chunks=[],this.err=t,this.msg=this.strm.msg},r.Deflate=p,r.deflate=i,r.deflateRaw=function(t,e){return(e=e||{}).raw=!0,i(t,e)},r.gzip=function(t,e){return(e=e||{}).gzip=!0,i(t,e)}},{"./utils/common":41,"./utils/strings":42,"./zlib/deflate":46,"./zlib/messages":51,"./zlib/zstream":53}],40:[function(t,e,r){"use strict";var d=t("./zlib/inflate"),c=t("./utils/common"),p=t("./utils/strings"),m=t("./zlib/constants"),i=t("./zlib/messages"),n=t("./zlib/zstream"),s=t("./zlib/gzheader"),_=Object.prototype.toString;function a(t){if(!(this instanceof a))return new a(t);this.options=c.assign({chunkSize:16384,windowBits:0,to:""},t||{});var e=this.options;e.raw&&0<=e.windowBits&&e.windowBits<16&&(e.windowBits=-e.windowBits,0===e.windowBits&&(e.windowBits=-15)),!(0<=e.windowBits&&e.windowBits<16)||t&&t.windowBits||(e.windowBits+=32),15<e.windowBits&&e.windowBits<48&&0==(15&e.windowBits)&&(e.windowBits|=15),this.err=0,this.msg="",this.ended=!1,this.chunks=[],this.strm=new n,this.strm.avail_out=0;var r=d.inflateInit2(this.strm,e.windowBits);if(r!==m.Z_OK)throw new Error(i[r]);this.header=new s,d.inflateGetHeader(this.strm,this.header)}function o(t,e){var r=new a(e);if(r.push(t,!0),r.err)throw r.msg||i[r.err];return r.result}a.prototype.push=function(t,e){var r,i,n,s,a,o,h=this.strm,u=this.options.chunkSize,l=this.options.dictionary,f=!1;if(this.ended)return!1;i=e===~~e?e:!0===e?m.Z_FINISH:m.Z_NO_FLUSH,"string"==typeof t?h.input=p.binstring2buf(t):"[object ArrayBuffer]"===_.call(t)?h.input=new Uint8Array(t):h.input=t,h.next_in=0,h.avail_in=h.input.length;do{if(0===h.avail_out&&(h.output=new c.Buf8(u),h.next_out=0,h.avail_out=u),(r=d.inflate(h,m.Z_NO_FLUSH))===m.Z_NEED_DICT&&l&&(o="string"==typeof l?p.string2buf(l):"[object ArrayBuffer]"===_.call(l)?new Uint8Array(l):l,r=d.inflateSetDictionary(this.strm,o)),r===m.Z_BUF_ERROR&&!0===f&&(r=m.Z_OK,f=!1),r!==m.Z_STREAM_END&&r!==m.Z_OK)return this.onEnd(r),!(this.ended=!0);h.next_out&&(0!==h.avail_out&&r!==m.Z_STREAM_END&&(0!==h.avail_in||i!==m.Z_FINISH&&i!==m.Z_SYNC_FLUSH)||("string"===this.options.to?(n=p.utf8border(h.output,h.next_out),s=h.next_out-n,a=p.buf2string(h.output,n),h.next_out=s,h.avail_out=u-s,s&&c.arraySet(h.output,h.output,n,s,0),this.onData(a)):this.onData(c.shrinkBuf(h.output,h.next_out)))),0===h.avail_in&&0===h.avail_out&&(f=!0)}while((0<h.avail_in||0===h.avail_out)&&r!==m.Z_STREAM_END);return r===m.Z_STREAM_END&&(i=m.Z_FINISH),i===m.Z_FINISH?(r=d.inflateEnd(this.strm),this.onEnd(r),this.ended=!0,r===m.Z_OK):i!==m.Z_SYNC_FLUSH||(this.onEnd(m.Z_OK),!(h.avail_out=0))},a.prototype.onData=function(t){this.chunks.push(t)},a.prototype.onEnd=function(t){t===m.Z_OK&&("string"===this.options.to?this.result=this.chunks.join(""):this.result=c.flattenChunks(this.chunks)),this.chunks=[],this.err=t,this.msg=this.strm.msg},r.Inflate=a,r.inflate=o,r.inflateRaw=function(t,e){return(e=e||{}).raw=!0,o(t,e)},r.ungzip=o},{"./utils/common":41,"./utils/strings":42,"./zlib/constants":44,"./zlib/gzheader":47,"./zlib/inflate":49,"./zlib/messages":51,"./zlib/zstream":53}],41:[function(t,e,r){"use strict";var i="undefined"!=typeof Uint8Array&&"undefined"!=typeof Uint16Array&&"undefined"!=typeof Int32Array;r.assign=function(t){for(var e=Array.prototype.slice.call(arguments,1);e.length;){var r=e.shift();if(r){if("object"!=typeof r)throw new TypeError(r+"must be non-object");for(var i in r)r.hasOwnProperty(i)&&(t[i]=r[i])}}return t},r.shrinkBuf=function(t,e){return t.length===e?t:t.subarray?t.subarray(0,e):(t.length=e,t)};var n={arraySet:function(t,e,r,i,n){if(e.subarray&&t.subarray)t.set(e.subarray(r,r+i),n);else for(var s=0;s<i;s++)t[n+s]=e[r+s]},flattenChunks:function(t){var e,r,i,n,s,a;for(e=i=0,r=t.length;e<r;e++)i+=t[e].length;for(a=new Uint8Array(i),e=n=0,r=t.length;e<r;e++)s=t[e],a.set(s,n),n+=s.length;return a}},s={arraySet:function(t,e,r,i,n){for(var s=0;s<i;s++)t[n+s]=e[r+s]},flattenChunks:function(t){return[].concat.apply([],t)}};r.setTyped=function(t){t?(r.Buf8=Uint8Array,r.Buf16=Uint16Array,r.Buf32=Int32Array,r.assign(r,n)):(r.Buf8=Array,r.Buf16=Array,r.Buf32=Array,r.assign(r,s))},r.setTyped(i)},{}],42:[function(t,e,r){"use strict";var h=t("./common"),n=!0,s=!0;try{String.fromCharCode.apply(null,[0])}catch(t){n=!1}try{String.fromCharCode.apply(null,new Uint8Array(1))}catch(t){s=!1}for(var u=new h.Buf8(256),i=0;i<256;i++)u[i]=252<=i?6:248<=i?5:240<=i?4:224<=i?3:192<=i?2:1;function l(t,e){if(e<65537&&(t.subarray&&s||!t.subarray&&n))return String.fromCharCode.apply(null,h.shrinkBuf(t,e));for(var r="",i=0;i<e;i++)r+=String.fromCharCode(t[i]);return r}u[254]=u[254]=1,r.string2buf=function(t){var e,r,i,n,s,a=t.length,o=0;for(n=0;n<a;n++)55296==(64512&(r=t.charCodeAt(n)))&&n+1<a&&56320==(64512&(i=t.charCodeAt(n+1)))&&(r=65536+(r-55296<<10)+(i-56320),n++),o+=r<128?1:r<2048?2:r<65536?3:4;for(e=new h.Buf8(o),n=s=0;s<o;n++)55296==(64512&(r=t.charCodeAt(n)))&&n+1<a&&56320==(64512&(i=t.charCodeAt(n+1)))&&(r=65536+(r-55296<<10)+(i-56320),n++),r<128?e[s++]=r:(r<2048?e[s++]=192|r>>>6:(r<65536?e[s++]=224|r>>>12:(e[s++]=240|r>>>18,e[s++]=128|r>>>12&63),e[s++]=128|r>>>6&63),e[s++]=128|63&r);return e},r.buf2binstring=function(t){return l(t,t.length)},r.binstring2buf=function(t){for(var e=new h.Buf8(t.length),r=0,i=e.length;r<i;r++)e[r]=t.charCodeAt(r);return e},r.buf2string=function(t,e){var r,i,n,s,a=e||t.length,o=new Array(2*a);for(r=i=0;r<a;)if((n=t[r++])<128)o[i++]=n;else if(4<(s=u[n]))o[i++]=65533,r+=s-1;else{for(n&=2===s?31:3===s?15:7;1<s&&r<a;)n=n<<6|63&t[r++],s--;1<s?o[i++]=65533:n<65536?o[i++]=n:(n-=65536,o[i++]=55296|n>>10&1023,o[i++]=56320|1023&n)}return l(o,i)},r.utf8border=function(t,e){var r;for((e=e||t.length)>t.length&&(e=t.length),r=e-1;0<=r&&128==(192&t[r]);)r--;return r<0?e:0===r?e:r+u[t[r]]>e?r:e}},{"./common":41}],43:[function(t,e,r){"use strict";e.exports=function(t,e,r,i){for(var n=65535&t|0,s=t>>>16&65535|0,a=0;0!==r;){for(r-=a=2e3<r?2e3:r;s=s+(n=n+e[i++]|0)|0,--a;);n%=65521,s%=65521}return n|s<<16|0}},{}],44:[function(t,e,r){"use strict";e.exports={Z_NO_FLUSH:0,Z_PARTIAL_FLUSH:1,Z_SYNC_FLUSH:2,Z_FULL_FLUSH:3,Z_FINISH:4,Z_BLOCK:5,Z_TREES:6,Z_OK:0,Z_STREAM_END:1,Z_NEED_DICT:2,Z_ERRNO:-1,Z_STREAM_ERROR:-2,Z_DATA_ERROR:-3,Z_BUF_ERROR:-5,Z_NO_COMPRESSION:0,Z_BEST_SPEED:1,Z_BEST_COMPRESSION:9,Z_DEFAULT_COMPRESSION:-1,Z_FILTERED:1,Z_HUFFMAN_ONLY:2,Z_RLE:3,Z_FIXED:4,Z_DEFAULT_STRATEGY:0,Z_BINARY:0,Z_TEXT:1,Z_UNKNOWN:2,Z_DEFLATED:8}},{}],45:[function(t,e,r){"use strict";var o=function(){for(var t,e=[],r=0;r<256;r++){t=r;for(var i=0;i<8;i++)t=1&t?3988292384^t>>>1:t>>>1;e[r]=t}return e}();e.exports=function(t,e,r,i){var n=o,s=i+r;t^=-1;for(var a=i;a<s;a++)t=t>>>8^n[255&(t^e[a])];return-1^t}},{}],46:[function(t,e,r){"use strict";var h,d=t("../utils/common"),u=t("./trees"),c=t("./adler32"),p=t("./crc32"),i=t("./messages"),l=0,f=4,m=0,_=-2,g=-1,b=4,n=2,v=8,y=9,s=286,a=30,o=19,w=2*s+1,k=15,x=3,S=258,z=S+x+1,C=42,E=113,A=1,I=2,O=3,B=4;function R(t,e){return t.msg=i[e],e}function T(t){return(t<<1)-(4<t?9:0)}function D(t){for(var e=t.length;0<=--e;)t[e]=0}function F(t){var e=t.state,r=e.pending;r>t.avail_out&&(r=t.avail_out),0!==r&&(d.arraySet(t.output,e.pending_buf,e.pending_out,r,t.next_out),t.next_out+=r,e.pending_out+=r,t.total_out+=r,t.avail_out-=r,e.pending-=r,0===e.pending&&(e.pending_out=0))}function N(t,e){u._tr_flush_block(t,0<=t.block_start?t.block_start:-1,t.strstart-t.block_start,e),t.block_start=t.strstart,F(t.strm)}function U(t,e){t.pending_buf[t.pending++]=e}function P(t,e){t.pending_buf[t.pending++]=e>>>8&255,t.pending_buf[t.pending++]=255&e}function L(t,e){var r,i,n=t.max_chain_length,s=t.strstart,a=t.prev_length,o=t.nice_match,h=t.strstart>t.w_size-z?t.strstart-(t.w_size-z):0,u=t.window,l=t.w_mask,f=t.prev,d=t.strstart+S,c=u[s+a-1],p=u[s+a];t.prev_length>=t.good_match&&(n>>=2),o>t.lookahead&&(o=t.lookahead);do{if(u[(r=e)+a]===p&&u[r+a-1]===c&&u[r]===u[s]&&u[++r]===u[s+1]){s+=2,r++;do{}while(u[++s]===u[++r]&&u[++s]===u[++r]&&u[++s]===u[++r]&&u[++s]===u[++r]&&u[++s]===u[++r]&&u[++s]===u[++r]&&u[++s]===u[++r]&&u[++s]===u[++r]&&s<d);if(i=S-(d-s),s=d-S,a<i){if(t.match_start=e,o<=(a=i))break;c=u[s+a-1],p=u[s+a]}}}while((e=f[e&l])>h&&0!=--n);return a<=t.lookahead?a:t.lookahead}function j(t){var e,r,i,n,s,a,o,h,u,l,f=t.w_size;do{if(n=t.window_size-t.lookahead-t.strstart,t.strstart>=f+(f-z)){for(d.arraySet(t.window,t.window,f,f,0),t.match_start-=f,t.strstart-=f,t.block_start-=f,e=r=t.hash_size;i=t.head[--e],t.head[e]=f<=i?i-f:0,--r;);for(e=r=f;i=t.prev[--e],t.prev[e]=f<=i?i-f:0,--r;);n+=f}if(0===t.strm.avail_in)break;if(a=t.strm,o=t.window,h=t.strstart+t.lookahead,u=n,l=void 0,l=a.avail_in,u<l&&(l=u),r=0===l?0:(a.avail_in-=l,d.arraySet(o,a.input,a.next_in,l,h),1===a.state.wrap?a.adler=c(a.adler,o,l,h):2===a.state.wrap&&(a.adler=p(a.adler,o,l,h)),a.next_in+=l,a.total_in+=l,l),t.lookahead+=r,t.lookahead+t.insert>=x)for(s=t.strstart-t.insert,t.ins_h=t.window[s],t.ins_h=(t.ins_h<<t.hash_shift^t.window[s+1])&t.hash_mask;t.insert&&(t.ins_h=(t.ins_h<<t.hash_shift^t.window[s+x-1])&t.hash_mask,t.prev[s&t.w_mask]=t.head[t.ins_h],t.head[t.ins_h]=s,s++,t.insert--,!(t.lookahead+t.insert<x)););}while(t.lookahead<z&&0!==t.strm.avail_in)}function Z(t,e){for(var r,i;;){if(t.lookahead<z){if(j(t),t.lookahead<z&&e===l)return A;if(0===t.lookahead)break}if(r=0,t.lookahead>=x&&(t.ins_h=(t.ins_h<<t.hash_shift^t.window[t.strstart+x-1])&t.hash_mask,r=t.prev[t.strstart&t.w_mask]=t.head[t.ins_h],t.head[t.ins_h]=t.strstart),0!==r&&t.strstart-r<=t.w_size-z&&(t.match_length=L(t,r)),t.match_length>=x)if(i=u._tr_tally(t,t.strstart-t.match_start,t.match_length-x),t.lookahead-=t.match_length,t.match_length<=t.max_lazy_match&&t.lookahead>=x){for(t.match_length--;t.strstart++,t.ins_h=(t.ins_h<<t.hash_shift^t.window[t.strstart+x-1])&t.hash_mask,r=t.prev[t.strstart&t.w_mask]=t.head[t.ins_h],t.head[t.ins_h]=t.strstart,0!=--t.match_length;);t.strstart++}else t.strstart+=t.match_length,t.match_length=0,t.ins_h=t.window[t.strstart],t.ins_h=(t.ins_h<<t.hash_shift^t.window[t.strstart+1])&t.hash_mask;else i=u._tr_tally(t,0,t.window[t.strstart]),t.lookahead--,t.strstart++;if(i&&(N(t,!1),0===t.strm.avail_out))return A}return t.insert=t.strstart<x-1?t.strstart:x-1,e===f?(N(t,!0),0===t.strm.avail_out?O:B):t.last_lit&&(N(t,!1),0===t.strm.avail_out)?A:I}function W(t,e){for(var r,i,n;;){if(t.lookahead<z){if(j(t),t.lookahead<z&&e===l)return A;if(0===t.lookahead)break}if(r=0,t.lookahead>=x&&(t.ins_h=(t.ins_h<<t.hash_shift^t.window[t.strstart+x-1])&t.hash_mask,r=t.prev[t.strstart&t.w_mask]=t.head[t.ins_h],t.head[t.ins_h]=t.strstart),t.prev_length=t.match_length,t.prev_match=t.match_start,t.match_length=x-1,0!==r&&t.prev_length<t.max_lazy_match&&t.strstart-r<=t.w_size-z&&(t.match_length=L(t,r),t.match_length<=5&&(1===t.strategy||t.match_length===x&&4096<t.strstart-t.match_start)&&(t.match_length=x-1)),t.prev_length>=x&&t.match_length<=t.prev_length){for(n=t.strstart+t.lookahead-x,i=u._tr_tally(t,t.strstart-1-t.prev_match,t.prev_length-x),t.lookahead-=t.prev_length-1,t.prev_length-=2;++t.strstart<=n&&(t.ins_h=(t.ins_h<<t.hash_shift^t.window[t.strstart+x-1])&t.hash_mask,r=t.prev[t.strstart&t.w_mask]=t.head[t.ins_h],t.head[t.ins_h]=t.strstart),0!=--t.prev_length;);if(t.match_available=0,t.match_length=x-1,t.strstart++,i&&(N(t,!1),0===t.strm.avail_out))return A}else if(t.match_available){if((i=u._tr_tally(t,0,t.window[t.strstart-1]))&&N(t,!1),t.strstart++,t.lookahead--,0===t.strm.avail_out)return A}else t.match_available=1,t.strstart++,t.lookahead--}return t.match_available&&(i=u._tr_tally(t,0,t.window[t.strstart-1]),t.match_available=0),t.insert=t.strstart<x-1?t.strstart:x-1,e===f?(N(t,!0),0===t.strm.avail_out?O:B):t.last_lit&&(N(t,!1),0===t.strm.avail_out)?A:I}function M(t,e,r,i,n){this.good_length=t,this.max_lazy=e,this.nice_length=r,this.max_chain=i,this.func=n}function H(){this.strm=null,this.status=0,this.pending_buf=null,this.pending_buf_size=0,this.pending_out=0,this.pending=0,this.wrap=0,this.gzhead=null,this.gzindex=0,this.method=v,this.last_flush=-1,this.w_size=0,this.w_bits=0,this.w_mask=0,this.window=null,this.window_size=0,this.prev=null,this.head=null,this.ins_h=0,this.hash_size=0,this.hash_bits=0,this.hash_mask=0,this.hash_shift=0,this.block_start=0,this.match_length=0,this.prev_match=0,this.match_available=0,this.strstart=0,this.match_start=0,this.lookahead=0,this.prev_length=0,this.max_chain_length=0,this.max_lazy_match=0,this.level=0,this.strategy=0,this.good_match=0,this.nice_match=0,this.dyn_ltree=new d.Buf16(2*w),this.dyn_dtree=new d.Buf16(2*(2*a+1)),this.bl_tree=new d.Buf16(2*(2*o+1)),D(this.dyn_ltree),D(this.dyn_dtree),D(this.bl_tree),this.l_desc=null,this.d_desc=null,this.bl_desc=null,this.bl_count=new d.Buf16(k+1),this.heap=new d.Buf16(2*s+1),D(this.heap),this.heap_len=0,this.heap_max=0,this.depth=new d.Buf16(2*s+1),D(this.depth),this.l_buf=0,this.lit_bufsize=0,this.last_lit=0,this.d_buf=0,this.opt_len=0,this.static_len=0,this.matches=0,this.insert=0,this.bi_buf=0,this.bi_valid=0}function G(t){var e;return t&&t.state?(t.total_in=t.total_out=0,t.data_type=n,(e=t.state).pending=0,e.pending_out=0,e.wrap<0&&(e.wrap=-e.wrap),e.status=e.wrap?C:E,t.adler=2===e.wrap?0:1,e.last_flush=l,u._tr_init(e),m):R(t,_)}function K(t){var e=G(t);return e===m&&function(t){t.window_size=2*t.w_size,D(t.head),t.max_lazy_match=h[t.level].max_lazy,t.good_match=h[t.level].good_length,t.nice_match=h[t.level].nice_length,t.max_chain_length=h[t.level].max_chain,t.strstart=0,t.block_start=0,t.lookahead=0,t.insert=0,t.match_length=t.prev_length=x-1,t.match_available=0,t.ins_h=0}(t.state),e}function Y(t,e,r,i,n,s){if(!t)return _;var a=1;if(e===g&&(e=6),i<0?(a=0,i=-i):15<i&&(a=2,i-=16),n<1||y<n||r!==v||i<8||15<i||e<0||9<e||s<0||b<s)return R(t,_);8===i&&(i=9);var o=new H;return(t.state=o).strm=t,o.wrap=a,o.gzhead=null,o.w_bits=i,o.w_size=1<<o.w_bits,o.w_mask=o.w_size-1,o.hash_bits=n+7,o.hash_size=1<<o.hash_bits,o.hash_mask=o.hash_size-1,o.hash_shift=~~((o.hash_bits+x-1)/x),o.window=new d.Buf8(2*o.w_size),o.head=new d.Buf16(o.hash_size),o.prev=new d.Buf16(o.w_size),o.lit_bufsize=1<<n+6,o.pending_buf_size=4*o.lit_bufsize,o.pending_buf=new d.Buf8(o.pending_buf_size),o.d_buf=1*o.lit_bufsize,o.l_buf=3*o.lit_bufsize,o.level=e,o.strategy=s,o.method=r,K(t)}h=[new M(0,0,0,0,function(t,e){var r=65535;for(r>t.pending_buf_size-5&&(r=t.pending_buf_size-5);;){if(t.lookahead<=1){if(j(t),0===t.lookahead&&e===l)return A;if(0===t.lookahead)break}t.strstart+=t.lookahead,t.lookahead=0;var i=t.block_start+r;if((0===t.strstart||t.strstart>=i)&&(t.lookahead=t.strstart-i,t.strstart=i,N(t,!1),0===t.strm.avail_out))return A;if(t.strstart-t.block_start>=t.w_size-z&&(N(t,!1),0===t.strm.avail_out))return A}return t.insert=0,e===f?(N(t,!0),0===t.strm.avail_out?O:B):(t.strstart>t.block_start&&(N(t,!1),t.strm.avail_out),A)}),new M(4,4,8,4,Z),new M(4,5,16,8,Z),new M(4,6,32,32,Z),new M(4,4,16,16,W),new M(8,16,32,32,W),new M(8,16,128,128,W),new M(8,32,128,256,W),new M(32,128,258,1024,W),new M(32,258,258,4096,W)],r.deflateInit=function(t,e){return Y(t,e,v,15,8,0)},r.deflateInit2=Y,r.deflateReset=K,r.deflateResetKeep=G,r.deflateSetHeader=function(t,e){return t&&t.state?2!==t.state.wrap?_:(t.state.gzhead=e,m):_},r.deflate=function(t,e){var r,i,n,s;if(!t||!t.state||5<e||e<0)return t?R(t,_):_;if(i=t.state,!t.output||!t.input&&0!==t.avail_in||666===i.status&&e!==f)return R(t,0===t.avail_out?-5:_);if(i.strm=t,r=i.last_flush,i.last_flush=e,i.status===C)if(2===i.wrap)t.adler=0,U(i,31),U(i,139),U(i,8),i.gzhead?(U(i,(i.gzhead.text?1:0)+(i.gzhead.hcrc?2:0)+(i.gzhead.extra?4:0)+(i.gzhead.name?8:0)+(i.gzhead.comment?16:0)),U(i,255&i.gzhead.time),U(i,i.gzhead.time>>8&255),U(i,i.gzhead.time>>16&255),U(i,i.gzhead.time>>24&255),U(i,9===i.level?2:2<=i.strategy||i.level<2?4:0),U(i,255&i.gzhead.os),i.gzhead.extra&&i.gzhead.extra.length&&(U(i,255&i.gzhead.extra.length),U(i,i.gzhead.extra.length>>8&255)),i.gzhead.hcrc&&(t.adler=p(t.adler,i.pending_buf,i.pending,0)),i.gzindex=0,i.status=69):(U(i,0),U(i,0),U(i,0),U(i,0),U(i,0),U(i,9===i.level?2:2<=i.strategy||i.level<2?4:0),U(i,3),i.status=E);else{var a=v+(i.w_bits-8<<4)<<8;a|=(2<=i.strategy||i.level<2?0:i.level<6?1:6===i.level?2:3)<<6,0!==i.strstart&&(a|=32),a+=31-a%31,i.status=E,P(i,a),0!==i.strstart&&(P(i,t.adler>>>16),P(i,65535&t.adler)),t.adler=1}if(69===i.status)if(i.gzhead.extra){for(n=i.pending;i.gzindex<(65535&i.gzhead.extra.length)&&(i.pending!==i.pending_buf_size||(i.gzhead.hcrc&&i.pending>n&&(t.adler=p(t.adler,i.pending_buf,i.pending-n,n)),F(t),n=i.pending,i.pending!==i.pending_buf_size));)U(i,255&i.gzhead.extra[i.gzindex]),i.gzindex++;i.gzhead.hcrc&&i.pending>n&&(t.adler=p(t.adler,i.pending_buf,i.pending-n,n)),i.gzindex===i.gzhead.extra.length&&(i.gzindex=0,i.status=73)}else i.status=73;if(73===i.status)if(i.gzhead.name){n=i.pending;do{if(i.pending===i.pending_buf_size&&(i.gzhead.hcrc&&i.pending>n&&(t.adler=p(t.adler,i.pending_buf,i.pending-n,n)),F(t),n=i.pending,i.pending===i.pending_buf_size)){s=1;break}s=i.gzindex<i.gzhead.name.length?255&i.gzhead.name.charCodeAt(i.gzindex++):0,U(i,s)}while(0!==s);i.gzhead.hcrc&&i.pending>n&&(t.adler=p(t.adler,i.pending_buf,i.pending-n,n)),0===s&&(i.gzindex=0,i.status=91)}else i.status=91;if(91===i.status)if(i.gzhead.comment){n=i.pending;do{if(i.pending===i.pending_buf_size&&(i.gzhead.hcrc&&i.pending>n&&(t.adler=p(t.adler,i.pending_buf,i.pending-n,n)),F(t),n=i.pending,i.pending===i.pending_buf_size)){s=1;break}s=i.gzindex<i.gzhead.comment.length?255&i.gzhead.comment.charCodeAt(i.gzindex++):0,U(i,s)}while(0!==s);i.gzhead.hcrc&&i.pending>n&&(t.adler=p(t.adler,i.pending_buf,i.pending-n,n)),0===s&&(i.status=103)}else i.status=103;if(103===i.status&&(i.gzhead.hcrc?(i.pending+2>i.pending_buf_size&&F(t),i.pending+2<=i.pending_buf_size&&(U(i,255&t.adler),U(i,t.adler>>8&255),t.adler=0,i.status=E)):i.status=E),0!==i.pending){if(F(t),0===t.avail_out)return i.last_flush=-1,m}else if(0===t.avail_in&&T(e)<=T(r)&&e!==f)return R(t,-5);if(666===i.status&&0!==t.avail_in)return R(t,-5);if(0!==t.avail_in||0!==i.lookahead||e!==l&&666!==i.status){var o=2===i.strategy?function(t,e){for(var r;;){if(0===t.lookahead&&(j(t),0===t.lookahead)){if(e===l)return A;break}if(t.match_length=0,r=u._tr_tally(t,0,t.window[t.strstart]),t.lookahead--,t.strstart++,r&&(N(t,!1),0===t.strm.avail_out))return A}return t.insert=0,e===f?(N(t,!0),0===t.strm.avail_out?O:B):t.last_lit&&(N(t,!1),0===t.strm.avail_out)?A:I}(i,e):3===i.strategy?function(t,e){for(var r,i,n,s,a=t.window;;){if(t.lookahead<=S){if(j(t),t.lookahead<=S&&e===l)return A;if(0===t.lookahead)break}if(t.match_length=0,t.lookahead>=x&&0<t.strstart&&(i=a[n=t.strstart-1])===a[++n]&&i===a[++n]&&i===a[++n]){s=t.strstart+S;do{}while(i===a[++n]&&i===a[++n]&&i===a[++n]&&i===a[++n]&&i===a[++n]&&i===a[++n]&&i===a[++n]&&i===a[++n]&&n<s);t.match_length=S-(s-n),t.match_length>t.lookahead&&(t.match_length=t.lookahead)}if(t.match_length>=x?(r=u._tr_tally(t,1,t.match_length-x),t.lookahead-=t.match_length,t.strstart+=t.match_length,t.match_length=0):(r=u._tr_tally(t,0,t.window[t.strstart]),t.lookahead--,t.strstart++),r&&(N(t,!1),0===t.strm.avail_out))return A}return t.insert=0,e===f?(N(t,!0),0===t.strm.avail_out?O:B):t.last_lit&&(N(t,!1),0===t.strm.avail_out)?A:I}(i,e):h[i.level].func(i,e);if(o!==O&&o!==B||(i.status=666),o===A||o===O)return 0===t.avail_out&&(i.last_flush=-1),m;if(o===I&&(1===e?u._tr_align(i):5!==e&&(u._tr_stored_block(i,0,0,!1),3===e&&(D(i.head),0===i.lookahead&&(i.strstart=0,i.block_start=0,i.insert=0))),F(t),0===t.avail_out))return i.last_flush=-1,m}return e!==f?m:i.wrap<=0?1:(2===i.wrap?(U(i,255&t.adler),U(i,t.adler>>8&255),U(i,t.adler>>16&255),U(i,t.adler>>24&255),U(i,255&t.total_in),U(i,t.total_in>>8&255),U(i,t.total_in>>16&255),U(i,t.total_in>>24&255)):(P(i,t.adler>>>16),P(i,65535&t.adler)),F(t),0<i.wrap&&(i.wrap=-i.wrap),0!==i.pending?m:1)},r.deflateEnd=function(t){var e;return t&&t.state?(e=t.state.status)!==C&&69!==e&&73!==e&&91!==e&&103!==e&&e!==E&&666!==e?R(t,_):(t.state=null,e===E?R(t,-3):m):_},r.deflateSetDictionary=function(t,e){var r,i,n,s,a,o,h,u,l=e.length;if(!t||!t.state)return _;if(2===(s=(r=t.state).wrap)||1===s&&r.status!==C||r.lookahead)return _;for(1===s&&(t.adler=c(t.adler,e,l,0)),r.wrap=0,l>=r.w_size&&(0===s&&(D(r.head),r.strstart=0,r.block_start=0,r.insert=0),u=new d.Buf8(r.w_size),d.arraySet(u,e,l-r.w_size,r.w_size,0),e=u,l=r.w_size),a=t.avail_in,o=t.next_in,h=t.input,t.avail_in=l,t.next_in=0,t.input=e,j(r);r.lookahead>=x;){for(i=r.strstart,n=r.lookahead-(x-1);r.ins_h=(r.ins_h<<r.hash_shift^r.window[i+x-1])&r.hash_mask,r.prev[i&r.w_mask]=r.head[r.ins_h],r.head[r.ins_h]=i,i++,--n;);r.strstart=i,r.lookahead=x-1,j(r)}return r.strstart+=r.lookahead,r.block_start=r.strstart,r.insert=r.lookahead,r.lookahead=0,r.match_length=r.prev_length=x-1,r.match_available=0,t.next_in=o,t.input=h,t.avail_in=a,r.wrap=s,m},r.deflateInfo="pako deflate (from Nodeca project)"},{"../utils/common":41,"./adler32":43,"./crc32":45,"./messages":51,"./trees":52}],47:[function(t,e,r){"use strict";e.exports=function(){this.text=0,this.time=0,this.xflags=0,this.os=0,this.extra=null,this.extra_len=0,this.name="",this.comment="",this.hcrc=0,this.done=!1}},{}],48:[function(t,e,r){"use strict";e.exports=function(t,e){var r,i,n,s,a,o,h,u,l,f,d,c,p,m,_,g,b,v,y,w,k,x,S,z,C;r=t.state,i=t.next_in,z=t.input,n=i+(t.avail_in-5),s=t.next_out,C=t.output,a=s-(e-t.avail_out),o=s+(t.avail_out-257),h=r.dmax,u=r.wsize,l=r.whave,f=r.wnext,d=r.window,c=r.hold,p=r.bits,m=r.lencode,_=r.distcode,g=(1<<r.lenbits)-1,b=(1<<r.distbits)-1;t:do{p<15&&(c+=z[i++]<<p,p+=8,c+=z[i++]<<p,p+=8),v=m[c&g];e:for(;;){if(c>>>=y=v>>>24,p-=y,0===(y=v>>>16&255))C[s++]=65535&v;else{if(!(16&y)){if(0==(64&y)){v=m[(65535&v)+(c&(1<<y)-1)];continue e}if(32&y){r.mode=12;break t}t.msg="invalid literal/length code",r.mode=30;break t}w=65535&v,(y&=15)&&(p<y&&(c+=z[i++]<<p,p+=8),w+=c&(1<<y)-1,c>>>=y,p-=y),p<15&&(c+=z[i++]<<p,p+=8,c+=z[i++]<<p,p+=8),v=_[c&b];r:for(;;){if(c>>>=y=v>>>24,p-=y,!(16&(y=v>>>16&255))){if(0==(64&y)){v=_[(65535&v)+(c&(1<<y)-1)];continue r}t.msg="invalid distance code",r.mode=30;break t}if(k=65535&v,p<(y&=15)&&(c+=z[i++]<<p,(p+=8)<y&&(c+=z[i++]<<p,p+=8)),h<(k+=c&(1<<y)-1)){t.msg="invalid distance too far back",r.mode=30;break t}if(c>>>=y,p-=y,(y=s-a)<k){if(l<(y=k-y)&&r.sane){t.msg="invalid distance too far back",r.mode=30;break t}if(S=d,(x=0)===f){if(x+=u-y,y<w){for(w-=y;C[s++]=d[x++],--y;);x=s-k,S=C}}else if(f<y){if(x+=u+f-y,(y-=f)<w){for(w-=y;C[s++]=d[x++],--y;);if(x=0,f<w){for(w-=y=f;C[s++]=d[x++],--y;);x=s-k,S=C}}}else if(x+=f-y,y<w){for(w-=y;C[s++]=d[x++],--y;);x=s-k,S=C}for(;2<w;)C[s++]=S[x++],C[s++]=S[x++],C[s++]=S[x++],w-=3;w&&(C[s++]=S[x++],1<w&&(C[s++]=S[x++]))}else{for(x=s-k;C[s++]=C[x++],C[s++]=C[x++],C[s++]=C[x++],2<(w-=3););w&&(C[s++]=C[x++],1<w&&(C[s++]=C[x++]))}break}}break}}while(i<n&&s<o);i-=w=p>>3,c&=(1<<(p-=w<<3))-1,t.next_in=i,t.next_out=s,t.avail_in=i<n?n-i+5:5-(i-n),t.avail_out=s<o?o-s+257:257-(s-o),r.hold=c,r.bits=p}},{}],49:[function(t,e,r){"use strict";var I=t("../utils/common"),O=t("./adler32"),B=t("./crc32"),R=t("./inffast"),T=t("./inftrees"),D=1,F=2,N=0,U=-2,P=1,i=852,n=592;function L(t){return(t>>>24&255)+(t>>>8&65280)+((65280&t)<<8)+((255&t)<<24)}function s(){this.mode=0,this.last=!1,this.wrap=0,this.havedict=!1,this.flags=0,this.dmax=0,this.check=0,this.total=0,this.head=null,this.wbits=0,this.wsize=0,this.whave=0,this.wnext=0,this.window=null,this.hold=0,this.bits=0,this.length=0,this.offset=0,this.extra=0,this.lencode=null,this.distcode=null,this.lenbits=0,this.distbits=0,this.ncode=0,this.nlen=0,this.ndist=0,this.have=0,this.next=null,this.lens=new I.Buf16(320),this.work=new I.Buf16(288),this.lendyn=null,this.distdyn=null,this.sane=0,this.back=0,this.was=0}function a(t){var e;return t&&t.state?(e=t.state,t.total_in=t.total_out=e.total=0,t.msg="",e.wrap&&(t.adler=1&e.wrap),e.mode=P,e.last=0,e.havedict=0,e.dmax=32768,e.head=null,e.hold=0,e.bits=0,e.lencode=e.lendyn=new I.Buf32(i),e.distcode=e.distdyn=new I.Buf32(n),e.sane=1,e.back=-1,N):U}function o(t){var e;return t&&t.state?((e=t.state).wsize=0,e.whave=0,e.wnext=0,a(t)):U}function h(t,e){var r,i;return t&&t.state?(i=t.state,e<0?(r=0,e=-e):(r=1+(e>>4),e<48&&(e&=15)),e&&(e<8||15<e)?U:(null!==i.window&&i.wbits!==e&&(i.window=null),i.wrap=r,i.wbits=e,o(t))):U}function u(t,e){var r,i;return t?(i=new s,(t.state=i).window=null,(r=h(t,e))!==N&&(t.state=null),r):U}var l,f,d=!0;function j(t){if(d){var e;for(l=new I.Buf32(512),f=new I.Buf32(32),e=0;e<144;)t.lens[e++]=8;for(;e<256;)t.lens[e++]=9;for(;e<280;)t.lens[e++]=7;for(;e<288;)t.lens[e++]=8;for(T(D,t.lens,0,288,l,0,t.work,{bits:9}),e=0;e<32;)t.lens[e++]=5;T(F,t.lens,0,32,f,0,t.work,{bits:5}),d=!1}t.lencode=l,t.lenbits=9,t.distcode=f,t.distbits=5}function Z(t,e,r,i){var n,s=t.state;return null===s.window&&(s.wsize=1<<s.wbits,s.wnext=0,s.whave=0,s.window=new I.Buf8(s.wsize)),i>=s.wsize?(I.arraySet(s.window,e,r-s.wsize,s.wsize,0),s.wnext=0,s.whave=s.wsize):(i<(n=s.wsize-s.wnext)&&(n=i),I.arraySet(s.window,e,r-i,n,s.wnext),(i-=n)?(I.arraySet(s.window,e,r-i,i,0),s.wnext=i,s.whave=s.wsize):(s.wnext+=n,s.wnext===s.wsize&&(s.wnext=0),s.whave<s.wsize&&(s.whave+=n))),0}r.inflateReset=o,r.inflateReset2=h,r.inflateResetKeep=a,r.inflateInit=function(t){return u(t,15)},r.inflateInit2=u,r.inflate=function(t,e){var r,i,n,s,a,o,h,u,l,f,d,c,p,m,_,g,b,v,y,w,k,x,S,z,C=0,E=new I.Buf8(4),A=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15];if(!t||!t.state||!t.output||!t.input&&0!==t.avail_in)return U;12===(r=t.state).mode&&(r.mode=13),a=t.next_out,n=t.output,h=t.avail_out,s=t.next_in,i=t.input,o=t.avail_in,u=r.hold,l=r.bits,f=o,d=h,x=N;t:for(;;)switch(r.mode){case P:if(0===r.wrap){r.mode=13;break}for(;l<16;){if(0===o)break t;o--,u+=i[s++]<<l,l+=8}if(2&r.wrap&&35615===u){E[r.check=0]=255&u,E[1]=u>>>8&255,r.check=B(r.check,E,2,0),l=u=0,r.mode=2;break}if(r.flags=0,r.head&&(r.head.done=!1),!(1&r.wrap)||(((255&u)<<8)+(u>>8))%31){t.msg="incorrect header check",r.mode=30;break}if(8!=(15&u)){t.msg="unknown compression method",r.mode=30;break}if(l-=4,k=8+(15&(u>>>=4)),0===r.wbits)r.wbits=k;else if(k>r.wbits){t.msg="invalid window size",r.mode=30;break}r.dmax=1<<k,t.adler=r.check=1,r.mode=512&u?10:12,l=u=0;break;case 2:for(;l<16;){if(0===o)break t;o--,u+=i[s++]<<l,l+=8}if(r.flags=u,8!=(255&r.flags)){t.msg="unknown compression method",r.mode=30;break}if(57344&r.flags){t.msg="unknown header flags set",r.mode=30;break}r.head&&(r.head.text=u>>8&1),512&r.flags&&(E[0]=255&u,E[1]=u>>>8&255,r.check=B(r.check,E,2,0)),l=u=0,r.mode=3;case 3:for(;l<32;){if(0===o)break t;o--,u+=i[s++]<<l,l+=8}r.head&&(r.head.time=u),512&r.flags&&(E[0]=255&u,E[1]=u>>>8&255,E[2]=u>>>16&255,E[3]=u>>>24&255,r.check=B(r.check,E,4,0)),l=u=0,r.mode=4;case 4:for(;l<16;){if(0===o)break t;o--,u+=i[s++]<<l,l+=8}r.head&&(r.head.xflags=255&u,r.head.os=u>>8),512&r.flags&&(E[0]=255&u,E[1]=u>>>8&255,r.check=B(r.check,E,2,0)),l=u=0,r.mode=5;case 5:if(1024&r.flags){for(;l<16;){if(0===o)break t;o--,u+=i[s++]<<l,l+=8}r.length=u,r.head&&(r.head.extra_len=u),512&r.flags&&(E[0]=255&u,E[1]=u>>>8&255,r.check=B(r.check,E,2,0)),l=u=0}else r.head&&(r.head.extra=null);r.mode=6;case 6:if(1024&r.flags&&(o<(c=r.length)&&(c=o),c&&(r.head&&(k=r.head.extra_len-r.length,r.head.extra||(r.head.extra=new Array(r.head.extra_len)),I.arraySet(r.head.extra,i,s,c,k)),512&r.flags&&(r.check=B(r.check,i,c,s)),o-=c,s+=c,r.length-=c),r.length))break t;r.length=0,r.mode=7;case 7:if(2048&r.flags){if(0===o)break t;for(c=0;k=i[s+c++],r.head&&k&&r.length<65536&&(r.head.name+=String.fromCharCode(k)),k&&c<o;);if(512&r.flags&&(r.check=B(r.check,i,c,s)),o-=c,s+=c,k)break t}else r.head&&(r.head.name=null);r.length=0,r.mode=8;case 8:if(4096&r.flags){if(0===o)break t;for(c=0;k=i[s+c++],r.head&&k&&r.length<65536&&(r.head.comment+=String.fromCharCode(k)),k&&c<o;);if(512&r.flags&&(r.check=B(r.check,i,c,s)),o-=c,s+=c,k)break t}else r.head&&(r.head.comment=null);r.mode=9;case 9:if(512&r.flags){for(;l<16;){if(0===o)break t;o--,u+=i[s++]<<l,l+=8}if(u!==(65535&r.check)){t.msg="header crc mismatch",r.mode=30;break}l=u=0}r.head&&(r.head.hcrc=r.flags>>9&1,r.head.done=!0),t.adler=r.check=0,r.mode=12;break;case 10:for(;l<32;){if(0===o)break t;o--,u+=i[s++]<<l,l+=8}t.adler=r.check=L(u),l=u=0,r.mode=11;case 11:if(0===r.havedict)return t.next_out=a,t.avail_out=h,t.next_in=s,t.avail_in=o,r.hold=u,r.bits=l,2;t.adler=r.check=1,r.mode=12;case 12:if(5===e||6===e)break t;case 13:if(r.last){u>>>=7&l,l-=7&l,r.mode=27;break}for(;l<3;){if(0===o)break t;o--,u+=i[s++]<<l,l+=8}switch(r.last=1&u,l-=1,3&(u>>>=1)){case 0:r.mode=14;break;case 1:if(j(r),r.mode=20,6!==e)break;u>>>=2,l-=2;break t;case 2:r.mode=17;break;case 3:t.msg="invalid block type",r.mode=30}u>>>=2,l-=2;break;case 14:for(u>>>=7&l,l-=7&l;l<32;){if(0===o)break t;o--,u+=i[s++]<<l,l+=8}if((65535&u)!=(u>>>16^65535)){t.msg="invalid stored block lengths",r.mode=30;break}if(r.length=65535&u,l=u=0,r.mode=15,6===e)break t;case 15:r.mode=16;case 16:if(c=r.length){if(o<c&&(c=o),h<c&&(c=h),0===c)break t;I.arraySet(n,i,s,c,a),o-=c,s+=c,h-=c,a+=c,r.length-=c;break}r.mode=12;break;case 17:for(;l<14;){if(0===o)break t;o--,u+=i[s++]<<l,l+=8}if(r.nlen=257+(31&u),u>>>=5,l-=5,r.ndist=1+(31&u),u>>>=5,l-=5,r.ncode=4+(15&u),u>>>=4,l-=4,286<r.nlen||30<r.ndist){t.msg="too many length or distance symbols",r.mode=30;break}r.have=0,r.mode=18;case 18:for(;r.have<r.ncode;){for(;l<3;){if(0===o)break t;o--,u+=i[s++]<<l,l+=8}r.lens[A[r.have++]]=7&u,u>>>=3,l-=3}for(;r.have<19;)r.lens[A[r.have++]]=0;if(r.lencode=r.lendyn,r.lenbits=7,S={bits:r.lenbits},x=T(0,r.lens,0,19,r.lencode,0,r.work,S),r.lenbits=S.bits,x){t.msg="invalid code lengths set",r.mode=30;break}r.have=0,r.mode=19;case 19:for(;r.have<r.nlen+r.ndist;){for(;g=(C=r.lencode[u&(1<<r.lenbits)-1])>>>16&255,b=65535&C,!((_=C>>>24)<=l);){if(0===o)break t;o--,u+=i[s++]<<l,l+=8}if(b<16)u>>>=_,l-=_,r.lens[r.have++]=b;else{if(16===b){for(z=_+2;l<z;){if(0===o)break t;o--,u+=i[s++]<<l,l+=8}if(u>>>=_,l-=_,0===r.have){t.msg="invalid bit length repeat",r.mode=30;break}k=r.lens[r.have-1],c=3+(3&u),u>>>=2,l-=2}else if(17===b){for(z=_+3;l<z;){if(0===o)break t;o--,u+=i[s++]<<l,l+=8}l-=_,k=0,c=3+(7&(u>>>=_)),u>>>=3,l-=3}else{for(z=_+7;l<z;){if(0===o)break t;o--,u+=i[s++]<<l,l+=8}l-=_,k=0,c=11+(127&(u>>>=_)),u>>>=7,l-=7}if(r.have+c>r.nlen+r.ndist){t.msg="invalid bit length repeat",r.mode=30;break}for(;c--;)r.lens[r.have++]=k}}if(30===r.mode)break;if(0===r.lens[256]){t.msg="invalid code -- missing end-of-block",r.mode=30;break}if(r.lenbits=9,S={bits:r.lenbits},x=T(D,r.lens,0,r.nlen,r.lencode,0,r.work,S),r.lenbits=S.bits,x){t.msg="invalid literal/lengths set",r.mode=30;break}if(r.distbits=6,r.distcode=r.distdyn,S={bits:r.distbits},x=T(F,r.lens,r.nlen,r.ndist,r.distcode,0,r.work,S),r.distbits=S.bits,x){t.msg="invalid distances set",r.mode=30;break}if(r.mode=20,6===e)break t;case 20:r.mode=21;case 21:if(6<=o&&258<=h){t.next_out=a,t.avail_out=h,t.next_in=s,t.avail_in=o,r.hold=u,r.bits=l,R(t,d),a=t.next_out,n=t.output,h=t.avail_out,s=t.next_in,i=t.input,o=t.avail_in,u=r.hold,l=r.bits,12===r.mode&&(r.back=-1);break}for(r.back=0;g=(C=r.lencode[u&(1<<r.lenbits)-1])>>>16&255,b=65535&C,!((_=C>>>24)<=l);){if(0===o)break t;o--,u+=i[s++]<<l,l+=8}if(g&&0==(240&g)){for(v=_,y=g,w=b;g=(C=r.lencode[w+((u&(1<<v+y)-1)>>v)])>>>16&255,b=65535&C,!(v+(_=C>>>24)<=l);){if(0===o)break t;o--,u+=i[s++]<<l,l+=8}u>>>=v,l-=v,r.back+=v}if(u>>>=_,l-=_,r.back+=_,r.length=b,0===g){r.mode=26;break}if(32&g){r.back=-1,r.mode=12;break}if(64&g){t.msg="invalid literal/length code",r.mode=30;break}r.extra=15&g,r.mode=22;case 22:if(r.extra){for(z=r.extra;l<z;){if(0===o)break t;o--,u+=i[s++]<<l,l+=8}r.length+=u&(1<<r.extra)-1,u>>>=r.extra,l-=r.extra,r.back+=r.extra}r.was=r.length,r.mode=23;case 23:for(;g=(C=r.distcode[u&(1<<r.distbits)-1])>>>16&255,b=65535&C,!((_=C>>>24)<=l);){if(0===o)break t;o--,u+=i[s++]<<l,l+=8}if(0==(240&g)){for(v=_,y=g,w=b;g=(C=r.distcode[w+((u&(1<<v+y)-1)>>v)])>>>16&255,b=65535&C,!(v+(_=C>>>24)<=l);){if(0===o)break t;o--,u+=i[s++]<<l,l+=8}u>>>=v,l-=v,r.back+=v}if(u>>>=_,l-=_,r.back+=_,64&g){t.msg="invalid distance code",r.mode=30;break}r.offset=b,r.extra=15&g,r.mode=24;case 24:if(r.extra){for(z=r.extra;l<z;){if(0===o)break t;o--,u+=i[s++]<<l,l+=8}r.offset+=u&(1<<r.extra)-1,u>>>=r.extra,l-=r.extra,r.back+=r.extra}if(r.offset>r.dmax){t.msg="invalid distance too far back",r.mode=30;break}r.mode=25;case 25:if(0===h)break t;if(c=d-h,r.offset>c){if((c=r.offset-c)>r.whave&&r.sane){t.msg="invalid distance too far back",r.mode=30;break}p=c>r.wnext?(c-=r.wnext,r.wsize-c):r.wnext-c,c>r.length&&(c=r.length),m=r.window}else m=n,p=a-r.offset,c=r.length;for(h<c&&(c=h),h-=c,r.length-=c;n[a++]=m[p++],--c;);0===r.length&&(r.mode=21);break;case 26:if(0===h)break t;n[a++]=r.length,h--,r.mode=21;break;case 27:if(r.wrap){for(;l<32;){if(0===o)break t;o--,u|=i[s++]<<l,l+=8}if(d-=h,t.total_out+=d,r.total+=d,d&&(t.adler=r.check=r.flags?B(r.check,n,d,a-d):O(r.check,n,d,a-d)),d=h,(r.flags?u:L(u))!==r.check){t.msg="incorrect data check",r.mode=30;break}l=u=0}r.mode=28;case 28:if(r.wrap&&r.flags){for(;l<32;){if(0===o)break t;o--,u+=i[s++]<<l,l+=8}if(u!==(4294967295&r.total)){t.msg="incorrect length check",r.mode=30;break}l=u=0}r.mode=29;case 29:x=1;break t;case 30:x=-3;break t;case 31:return-4;case 32:default:return U}return t.next_out=a,t.avail_out=h,t.next_in=s,t.avail_in=o,r.hold=u,r.bits=l,(r.wsize||d!==t.avail_out&&r.mode<30&&(r.mode<27||4!==e))&&Z(t,t.output,t.next_out,d-t.avail_out)?(r.mode=31,-4):(f-=t.avail_in,d-=t.avail_out,t.total_in+=f,t.total_out+=d,r.total+=d,r.wrap&&d&&(t.adler=r.check=r.flags?B(r.check,n,d,t.next_out-d):O(r.check,n,d,t.next_out-d)),t.data_type=r.bits+(r.last?64:0)+(12===r.mode?128:0)+(20===r.mode||15===r.mode?256:0),(0==f&&0===d||4===e)&&x===N&&(x=-5),x)},r.inflateEnd=function(t){if(!t||!t.state)return U;var e=t.state;return e.window&&(e.window=null),t.state=null,N},r.inflateGetHeader=function(t,e){var r;return t&&t.state?0==(2&(r=t.state).wrap)?U:((r.head=e).done=!1,N):U},r.inflateSetDictionary=function(t,e){var r,i=e.length;return t&&t.state?0!==(r=t.state).wrap&&11!==r.mode?U:11===r.mode&&O(1,e,i,0)!==r.check?-3:Z(t,e,i,i)?(r.mode=31,-4):(r.havedict=1,N):U},r.inflateInfo="pako inflate (from Nodeca project)"},{"../utils/common":41,"./adler32":43,"./crc32":45,"./inffast":48,"./inftrees":50}],50:[function(t,e,r){"use strict";var D=t("../utils/common"),F=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,0,0],N=[16,16,16,16,16,16,16,16,17,17,17,17,18,18,18,18,19,19,19,19,20,20,20,20,21,21,21,21,16,72,78],U=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0],P=[16,16,16,16,17,17,18,18,19,19,20,20,21,21,22,22,23,23,24,24,25,25,26,26,27,27,28,28,29,29,64,64];e.exports=function(t,e,r,i,n,s,a,o){var h,u,l,f,d,c,p,m,_,g=o.bits,b=0,v=0,y=0,w=0,k=0,x=0,S=0,z=0,C=0,E=0,A=null,I=0,O=new D.Buf16(16),B=new D.Buf16(16),R=null,T=0;for(b=0;b<=15;b++)O[b]=0;for(v=0;v<i;v++)O[e[r+v]]++;for(k=g,w=15;1<=w&&0===O[w];w--);if(w<k&&(k=w),0===w)return n[s++]=20971520,n[s++]=20971520,o.bits=1,0;for(y=1;y<w&&0===O[y];y++);for(k<y&&(k=y),b=z=1;b<=15;b++)if(z<<=1,(z-=O[b])<0)return-1;if(0<z&&(0===t||1!==w))return-1;for(B[1]=0,b=1;b<15;b++)B[b+1]=B[b]+O[b];for(v=0;v<i;v++)0!==e[r+v]&&(a[B[e[r+v]]++]=v);if(c=0===t?(A=R=a,19):1===t?(A=F,I-=257,R=N,T-=257,256):(A=U,R=P,-1),b=y,d=s,S=v=E=0,l=-1,f=(C=1<<(x=k))-1,1===t&&852<C||2===t&&592<C)return 1;for(;;){for(p=b-S,_=a[v]<c?(m=0,a[v]):a[v]>c?(m=R[T+a[v]],A[I+a[v]]):(m=96,0),h=1<<b-S,y=u=1<<x;n[d+(E>>S)+(u-=h)]=p<<24|m<<16|_|0,0!==u;);for(h=1<<b-1;E&h;)h>>=1;if(0!==h?(E&=h-1,E+=h):E=0,v++,0==--O[b]){if(b===w)break;b=e[r+a[v]]}if(k<b&&(E&f)!==l){for(0===S&&(S=k),d+=y,z=1<<(x=b-S);x+S<w&&!((z-=O[x+S])<=0);)x++,z<<=1;if(C+=1<<x,1===t&&852<C||2===t&&592<C)return 1;n[l=E&f]=k<<24|x<<16|d-s|0}}return 0!==E&&(n[d+E]=b-S<<24|64<<16|0),o.bits=k,0}},{"../utils/common":41}],51:[function(t,e,r){"use strict";e.exports={2:"need dictionary",1:"stream end",0:"","-1":"file error","-2":"stream error","-3":"data error","-4":"insufficient memory","-5":"buffer error","-6":"incompatible version"}},{}],52:[function(t,e,r){"use strict";var n=t("../utils/common"),o=0,h=1;function i(t){for(var e=t.length;0<=--e;)t[e]=0}var s=0,a=29,u=256,l=u+1+a,f=30,d=19,_=2*l+1,g=15,c=16,p=7,m=256,b=16,v=17,y=18,w=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0],k=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13],x=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7],S=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],z=new Array(2*(l+2));i(z);var C=new Array(2*f);i(C);var E=new Array(512);i(E);var A=new Array(256);i(A);var I=new Array(a);i(I);var O,B,R,T=new Array(f);function D(t,e,r,i,n){this.static_tree=t,this.extra_bits=e,this.extra_base=r,this.elems=i,this.max_length=n,this.has_stree=t&&t.length}function F(t,e){this.dyn_tree=t,this.max_code=0,this.stat_desc=e}function N(t){return t<256?E[t]:E[256+(t>>>7)]}function U(t,e){t.pending_buf[t.pending++]=255&e,t.pending_buf[t.pending++]=e>>>8&255}function P(t,e,r){t.bi_valid>c-r?(t.bi_buf|=e<<t.bi_valid&65535,U(t,t.bi_buf),t.bi_buf=e>>c-t.bi_valid,t.bi_valid+=r-c):(t.bi_buf|=e<<t.bi_valid&65535,t.bi_valid+=r)}function L(t,e,r){P(t,r[2*e],r[2*e+1])}function j(t,e){for(var r=0;r|=1&t,t>>>=1,r<<=1,0<--e;);return r>>>1}function Z(t,e,r){var i,n,s=new Array(g+1),a=0;for(i=1;i<=g;i++)s[i]=a=a+r[i-1]<<1;for(n=0;n<=e;n++){var o=t[2*n+1];0!==o&&(t[2*n]=j(s[o]++,o))}}function W(t){var e;for(e=0;e<l;e++)t.dyn_ltree[2*e]=0;for(e=0;e<f;e++)t.dyn_dtree[2*e]=0;for(e=0;e<d;e++)t.bl_tree[2*e]=0;t.dyn_ltree[2*m]=1,t.opt_len=t.static_len=0,t.last_lit=t.matches=0}function M(t){8<t.bi_valid?U(t,t.bi_buf):0<t.bi_valid&&(t.pending_buf[t.pending++]=t.bi_buf),t.bi_buf=0,t.bi_valid=0}function H(t,e,r,i){var n=2*e,s=2*r;return t[n]<t[s]||t[n]===t[s]&&i[e]<=i[r]}function G(t,e,r){for(var i=t.heap[r],n=r<<1;n<=t.heap_len&&(n<t.heap_len&&H(e,t.heap[n+1],t.heap[n],t.depth)&&n++,!H(e,i,t.heap[n],t.depth));)t.heap[r]=t.heap[n],r=n,n<<=1;t.heap[r]=i}function K(t,e,r){var i,n,s,a,o=0;if(0!==t.last_lit)for(;i=t.pending_buf[t.d_buf+2*o]<<8|t.pending_buf[t.d_buf+2*o+1],n=t.pending_buf[t.l_buf+o],o++,0===i?L(t,n,e):(L(t,(s=A[n])+u+1,e),0!==(a=w[s])&&P(t,n-=I[s],a),L(t,s=N(--i),r),0!==(a=k[s])&&P(t,i-=T[s],a)),o<t.last_lit;);L(t,m,e)}function Y(t,e){var r,i,n,s=e.dyn_tree,a=e.stat_desc.static_tree,o=e.stat_desc.has_stree,h=e.stat_desc.elems,u=-1;for(t.heap_len=0,t.heap_max=_,r=0;r<h;r++)0!==s[2*r]?(t.heap[++t.heap_len]=u=r,t.depth[r]=0):s[2*r+1]=0;for(;t.heap_len<2;)s[2*(n=t.heap[++t.heap_len]=u<2?++u:0)]=1,t.depth[n]=0,t.opt_len--,o&&(t.static_len-=a[2*n+1]);for(e.max_code=u,r=t.heap_len>>1;1<=r;r--)G(t,s,r);for(n=h;r=t.heap[1],t.heap[1]=t.heap[t.heap_len--],G(t,s,1),i=t.heap[1],t.heap[--t.heap_max]=r,t.heap[--t.heap_max]=i,s[2*n]=s[2*r]+s[2*i],t.depth[n]=(t.depth[r]>=t.depth[i]?t.depth[r]:t.depth[i])+1,s[2*r+1]=s[2*i+1]=n,t.heap[1]=n++,G(t,s,1),2<=t.heap_len;);t.heap[--t.heap_max]=t.heap[1],function(t,e){var r,i,n,s,a,o,h=e.dyn_tree,u=e.max_code,l=e.stat_desc.static_tree,f=e.stat_desc.has_stree,d=e.stat_desc.extra_bits,c=e.stat_desc.extra_base,p=e.stat_desc.max_length,m=0;for(s=0;s<=g;s++)t.bl_count[s]=0;for(h[2*t.heap[t.heap_max]+1]=0,r=t.heap_max+1;r<_;r++)p<(s=h[2*h[2*(i=t.heap[r])+1]+1]+1)&&(s=p,m++),h[2*i+1]=s,u<i||(t.bl_count[s]++,a=0,c<=i&&(a=d[i-c]),o=h[2*i],t.opt_len+=o*(s+a),f&&(t.static_len+=o*(l[2*i+1]+a)));if(0!==m){do{for(s=p-1;0===t.bl_count[s];)s--;t.bl_count[s]--,t.bl_count[s+1]+=2,t.bl_count[p]--,m-=2}while(0<m);for(s=p;0!==s;s--)for(i=t.bl_count[s];0!==i;)u<(n=t.heap[--r])||(h[2*n+1]!==s&&(t.opt_len+=(s-h[2*n+1])*h[2*n],h[2*n+1]=s),i--)}}(t,e),Z(s,u,t.bl_count)}function X(t,e,r){var i,n,s=-1,a=e[1],o=0,h=7,u=4;for(0===a&&(h=138,u=3),e[2*(r+1)+1]=65535,i=0;i<=r;i++)n=a,a=e[2*(i+1)+1],++o<h&&n===a||(o<u?t.bl_tree[2*n]+=o:0!==n?(n!==s&&t.bl_tree[2*n]++,t.bl_tree[2*b]++):o<=10?t.bl_tree[2*v]++:t.bl_tree[2*y]++,s=n,u=(o=0)===a?(h=138,3):n===a?(h=6,3):(h=7,4))}function V(t,e,r){var i,n,s=-1,a=e[1],o=0,h=7,u=4;for(0===a&&(h=138,u=3),i=0;i<=r;i++)if(n=a,a=e[2*(i+1)+1],!(++o<h&&n===a)){if(o<u)for(;L(t,n,t.bl_tree),0!=--o;);else 0!==n?(n!==s&&(L(t,n,t.bl_tree),o--),L(t,b,t.bl_tree),P(t,o-3,2)):o<=10?(L(t,v,t.bl_tree),P(t,o-3,3)):(L(t,y,t.bl_tree),P(t,o-11,7));s=n,u=(o=0)===a?(h=138,3):n===a?(h=6,3):(h=7,4)}}i(T);var q=!1;function J(t,e,r,i){P(t,(s<<1)+(i?1:0),3),function(t,e,r,i){M(t),i&&(U(t,r),U(t,~r)),n.arraySet(t.pending_buf,t.window,e,r,t.pending),t.pending+=r}(t,e,r,!0)}r._tr_init=function(t){q||(function(){var t,e,r,i,n,s=new Array(g+1);for(i=r=0;i<a-1;i++)for(I[i]=r,t=0;t<1<<w[i];t++)A[r++]=i;for(A[r-1]=i,i=n=0;i<16;i++)for(T[i]=n,t=0;t<1<<k[i];t++)E[n++]=i;for(n>>=7;i<f;i++)for(T[i]=n<<7,t=0;t<1<<k[i]-7;t++)E[256+n++]=i;for(e=0;e<=g;e++)s[e]=0;for(t=0;t<=143;)z[2*t+1]=8,t++,s[8]++;for(;t<=255;)z[2*t+1]=9,t++,s[9]++;for(;t<=279;)z[2*t+1]=7,t++,s[7]++;for(;t<=287;)z[2*t+1]=8,t++,s[8]++;for(Z(z,l+1,s),t=0;t<f;t++)C[2*t+1]=5,C[2*t]=j(t,5);O=new D(z,w,u+1,l,g),B=new D(C,k,0,f,g),R=new D(new Array(0),x,0,d,p)}(),q=!0),t.l_desc=new F(t.dyn_ltree,O),t.d_desc=new F(t.dyn_dtree,B),t.bl_desc=new F(t.bl_tree,R),t.bi_buf=0,t.bi_valid=0,W(t)},r._tr_stored_block=J,r._tr_flush_block=function(t,e,r,i){var n,s,a=0;0<t.level?(2===t.strm.data_type&&(t.strm.data_type=function(t){var e,r=4093624447;for(e=0;e<=31;e++,r>>>=1)if(1&r&&0!==t.dyn_ltree[2*e])return o;if(0!==t.dyn_ltree[18]||0!==t.dyn_ltree[20]||0!==t.dyn_ltree[26])return h;for(e=32;e<u;e++)if(0!==t.dyn_ltree[2*e])return h;return o}(t)),Y(t,t.l_desc),Y(t,t.d_desc),a=function(t){var e;for(X(t,t.dyn_ltree,t.l_desc.max_code),X(t,t.dyn_dtree,t.d_desc.max_code),Y(t,t.bl_desc),e=d-1;3<=e&&0===t.bl_tree[2*S[e]+1];e--);return t.opt_len+=3*(e+1)+5+5+4,e}(t),n=t.opt_len+3+7>>>3,(s=t.static_len+3+7>>>3)<=n&&(n=s)):n=s=r+5,r+4<=n&&-1!==e?J(t,e,r,i):4===t.strategy||s===n?(P(t,2+(i?1:0),3),K(t,z,C)):(P(t,4+(i?1:0),3),function(t,e,r,i){var n;for(P(t,e-257,5),P(t,r-1,5),P(t,i-4,4),n=0;n<i;n++)P(t,t.bl_tree[2*S[n]+1],3);V(t,t.dyn_ltree,e-1),V(t,t.dyn_dtree,r-1)}(t,t.l_desc.max_code+1,t.d_desc.max_code+1,a+1),K(t,t.dyn_ltree,t.dyn_dtree)),W(t),i&&M(t)},r._tr_tally=function(t,e,r){return t.pending_buf[t.d_buf+2*t.last_lit]=e>>>8&255,t.pending_buf[t.d_buf+2*t.last_lit+1]=255&e,t.pending_buf[t.l_buf+t.last_lit]=255&r,t.last_lit++,0===e?t.dyn_ltree[2*r]++:(t.matches++,e--,t.dyn_ltree[2*(A[r]+u+1)]++,t.dyn_dtree[2*N(e)]++),t.last_lit===t.lit_bufsize-1},r._tr_align=function(t){P(t,2,3),L(t,m,z),function(t){16===t.bi_valid?(U(t,t.bi_buf),t.bi_buf=0,t.bi_valid=0):8<=t.bi_valid&&(t.pending_buf[t.pending++]=255&t.bi_buf,t.bi_buf>>=8,t.bi_valid-=8)}(t)}},{"../utils/common":41}],53:[function(t,e,r){"use strict";e.exports=function(){this.input=null,this.next_in=0,this.avail_in=0,this.total_in=0,this.output=null,this.next_out=0,this.avail_out=0,this.total_out=0,this.msg="",this.state=null,this.data_type=2,this.adler=0}},{}],54:[function(t,e,r){"use strict";e.exports="function"==typeof setImmediate?setImmediate:function(){var t=[].slice.apply(arguments);t.splice(1,0,0),setTimeout.apply(null,t)}},{}]},{},[10])(10)});
|
src/arborator-draft/speedtest.oneBigConllTag.html
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
src/arborator-draft/speedtest.separateConllTags.html
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
src/evalatin2024-latinpipe/LICENSE
ADDED
|
@@ -0,0 +1,373 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Mozilla Public License Version 2.0
|
| 2 |
+
==================================
|
| 3 |
+
|
| 4 |
+
1. Definitions
|
| 5 |
+
--------------
|
| 6 |
+
|
| 7 |
+
1.1. "Contributor"
|
| 8 |
+
means each individual or legal entity that creates, contributes to
|
| 9 |
+
the creation of, or owns Covered Software.
|
| 10 |
+
|
| 11 |
+
1.2. "Contributor Version"
|
| 12 |
+
means the combination of the Contributions of others (if any) used
|
| 13 |
+
by a Contributor and that particular Contributor's Contribution.
|
| 14 |
+
|
| 15 |
+
1.3. "Contribution"
|
| 16 |
+
means Covered Software of a particular Contributor.
|
| 17 |
+
|
| 18 |
+
1.4. "Covered Software"
|
| 19 |
+
means Source Code Form to which the initial Contributor has attached
|
| 20 |
+
the notice in Exhibit A, the Executable Form of such Source Code
|
| 21 |
+
Form, and Modifications of such Source Code Form, in each case
|
| 22 |
+
including portions thereof.
|
| 23 |
+
|
| 24 |
+
1.5. "Incompatible With Secondary Licenses"
|
| 25 |
+
means
|
| 26 |
+
|
| 27 |
+
(a) that the initial Contributor has attached the notice described
|
| 28 |
+
in Exhibit B to the Covered Software; or
|
| 29 |
+
|
| 30 |
+
(b) that the Covered Software was made available under the terms of
|
| 31 |
+
version 1.1 or earlier of the License, but not also under the
|
| 32 |
+
terms of a Secondary License.
|
| 33 |
+
|
| 34 |
+
1.6. "Executable Form"
|
| 35 |
+
means any form of the work other than Source Code Form.
|
| 36 |
+
|
| 37 |
+
1.7. "Larger Work"
|
| 38 |
+
means a work that combines Covered Software with other material, in
|
| 39 |
+
a separate file or files, that is not Covered Software.
|
| 40 |
+
|
| 41 |
+
1.8. "License"
|
| 42 |
+
means this document.
|
| 43 |
+
|
| 44 |
+
1.9. "Licensable"
|
| 45 |
+
means having the right to grant, to the maximum extent possible,
|
| 46 |
+
whether at the time of the initial grant or subsequently, any and
|
| 47 |
+
all of the rights conveyed by this License.
|
| 48 |
+
|
| 49 |
+
1.10. "Modifications"
|
| 50 |
+
means any of the following:
|
| 51 |
+
|
| 52 |
+
(a) any file in Source Code Form that results from an addition to,
|
| 53 |
+
deletion from, or modification of the contents of Covered
|
| 54 |
+
Software; or
|
| 55 |
+
|
| 56 |
+
(b) any new file in Source Code Form that contains any Covered
|
| 57 |
+
Software.
|
| 58 |
+
|
| 59 |
+
1.11. "Patent Claims" of a Contributor
|
| 60 |
+
means any patent claim(s), including without limitation, method,
|
| 61 |
+
process, and apparatus claims, in any patent Licensable by such
|
| 62 |
+
Contributor that would be infringed, but for the grant of the
|
| 63 |
+
License, by the making, using, selling, offering for sale, having
|
| 64 |
+
made, import, or transfer of either its Contributions or its
|
| 65 |
+
Contributor Version.
|
| 66 |
+
|
| 67 |
+
1.12. "Secondary License"
|
| 68 |
+
means either the GNU General Public License, Version 2.0, the GNU
|
| 69 |
+
Lesser General Public License, Version 2.1, the GNU Affero General
|
| 70 |
+
Public License, Version 3.0, or any later versions of those
|
| 71 |
+
licenses.
|
| 72 |
+
|
| 73 |
+
1.13. "Source Code Form"
|
| 74 |
+
means the form of the work preferred for making modifications.
|
| 75 |
+
|
| 76 |
+
1.14. "You" (or "Your")
|
| 77 |
+
means an individual or a legal entity exercising rights under this
|
| 78 |
+
License. For legal entities, "You" includes any entity that
|
| 79 |
+
controls, is controlled by, or is under common control with You. For
|
| 80 |
+
purposes of this definition, "control" means (a) the power, direct
|
| 81 |
+
or indirect, to cause the direction or management of such entity,
|
| 82 |
+
whether by contract or otherwise, or (b) ownership of more than
|
| 83 |
+
fifty percent (50%) of the outstanding shares or beneficial
|
| 84 |
+
ownership of such entity.
|
| 85 |
+
|
| 86 |
+
2. License Grants and Conditions
|
| 87 |
+
--------------------------------
|
| 88 |
+
|
| 89 |
+
2.1. Grants
|
| 90 |
+
|
| 91 |
+
Each Contributor hereby grants You a world-wide, royalty-free,
|
| 92 |
+
non-exclusive license:
|
| 93 |
+
|
| 94 |
+
(a) under intellectual property rights (other than patent or trademark)
|
| 95 |
+
Licensable by such Contributor to use, reproduce, make available,
|
| 96 |
+
modify, display, perform, distribute, and otherwise exploit its
|
| 97 |
+
Contributions, either on an unmodified basis, with Modifications, or
|
| 98 |
+
as part of a Larger Work; and
|
| 99 |
+
|
| 100 |
+
(b) under Patent Claims of such Contributor to make, use, sell, offer
|
| 101 |
+
for sale, have made, import, and otherwise transfer either its
|
| 102 |
+
Contributions or its Contributor Version.
|
| 103 |
+
|
| 104 |
+
2.2. Effective Date
|
| 105 |
+
|
| 106 |
+
The licenses granted in Section 2.1 with respect to any Contribution
|
| 107 |
+
become effective for each Contribution on the date the Contributor first
|
| 108 |
+
distributes such Contribution.
|
| 109 |
+
|
| 110 |
+
2.3. Limitations on Grant Scope
|
| 111 |
+
|
| 112 |
+
The licenses granted in this Section 2 are the only rights granted under
|
| 113 |
+
this License. No additional rights or licenses will be implied from the
|
| 114 |
+
distribution or licensing of Covered Software under this License.
|
| 115 |
+
Notwithstanding Section 2.1(b) above, no patent license is granted by a
|
| 116 |
+
Contributor:
|
| 117 |
+
|
| 118 |
+
(a) for any code that a Contributor has removed from Covered Software;
|
| 119 |
+
or
|
| 120 |
+
|
| 121 |
+
(b) for infringements caused by: (i) Your and any other third party's
|
| 122 |
+
modifications of Covered Software, or (ii) the combination of its
|
| 123 |
+
Contributions with other software (except as part of its Contributor
|
| 124 |
+
Version); or
|
| 125 |
+
|
| 126 |
+
(c) under Patent Claims infringed by Covered Software in the absence of
|
| 127 |
+
its Contributions.
|
| 128 |
+
|
| 129 |
+
This License does not grant any rights in the trademarks, service marks,
|
| 130 |
+
or logos of any Contributor (except as may be necessary to comply with
|
| 131 |
+
the notice requirements in Section 3.4).
|
| 132 |
+
|
| 133 |
+
2.4. Subsequent Licenses
|
| 134 |
+
|
| 135 |
+
No Contributor makes additional grants as a result of Your choice to
|
| 136 |
+
distribute the Covered Software under a subsequent version of this
|
| 137 |
+
License (see Section 10.2) or under the terms of a Secondary License (if
|
| 138 |
+
permitted under the terms of Section 3.3).
|
| 139 |
+
|
| 140 |
+
2.5. Representation
|
| 141 |
+
|
| 142 |
+
Each Contributor represents that the Contributor believes its
|
| 143 |
+
Contributions are its original creation(s) or it has sufficient rights
|
| 144 |
+
to grant the rights to its Contributions conveyed by this License.
|
| 145 |
+
|
| 146 |
+
2.6. Fair Use
|
| 147 |
+
|
| 148 |
+
This License is not intended to limit any rights You have under
|
| 149 |
+
applicable copyright doctrines of fair use, fair dealing, or other
|
| 150 |
+
equivalents.
|
| 151 |
+
|
| 152 |
+
2.7. Conditions
|
| 153 |
+
|
| 154 |
+
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
|
| 155 |
+
in Section 2.1.
|
| 156 |
+
|
| 157 |
+
3. Responsibilities
|
| 158 |
+
-------------------
|
| 159 |
+
|
| 160 |
+
3.1. Distribution of Source Form
|
| 161 |
+
|
| 162 |
+
All distribution of Covered Software in Source Code Form, including any
|
| 163 |
+
Modifications that You create or to which You contribute, must be under
|
| 164 |
+
the terms of this License. You must inform recipients that the Source
|
| 165 |
+
Code Form of the Covered Software is governed by the terms of this
|
| 166 |
+
License, and how they can obtain a copy of this License. You may not
|
| 167 |
+
attempt to alter or restrict the recipients' rights in the Source Code
|
| 168 |
+
Form.
|
| 169 |
+
|
| 170 |
+
3.2. Distribution of Executable Form
|
| 171 |
+
|
| 172 |
+
If You distribute Covered Software in Executable Form then:
|
| 173 |
+
|
| 174 |
+
(a) such Covered Software must also be made available in Source Code
|
| 175 |
+
Form, as described in Section 3.1, and You must inform recipients of
|
| 176 |
+
the Executable Form how they can obtain a copy of such Source Code
|
| 177 |
+
Form by reasonable means in a timely manner, at a charge no more
|
| 178 |
+
than the cost of distribution to the recipient; and
|
| 179 |
+
|
| 180 |
+
(b) You may distribute such Executable Form under the terms of this
|
| 181 |
+
License, or sublicense it under different terms, provided that the
|
| 182 |
+
license for the Executable Form does not attempt to limit or alter
|
| 183 |
+
the recipients' rights in the Source Code Form under this License.
|
| 184 |
+
|
| 185 |
+
3.3. Distribution of a Larger Work
|
| 186 |
+
|
| 187 |
+
You may create and distribute a Larger Work under terms of Your choice,
|
| 188 |
+
provided that You also comply with the requirements of this License for
|
| 189 |
+
the Covered Software. If the Larger Work is a combination of Covered
|
| 190 |
+
Software with a work governed by one or more Secondary Licenses, and the
|
| 191 |
+
Covered Software is not Incompatible With Secondary Licenses, this
|
| 192 |
+
License permits You to additionally distribute such Covered Software
|
| 193 |
+
under the terms of such Secondary License(s), so that the recipient of
|
| 194 |
+
the Larger Work may, at their option, further distribute the Covered
|
| 195 |
+
Software under the terms of either this License or such Secondary
|
| 196 |
+
License(s).
|
| 197 |
+
|
| 198 |
+
3.4. Notices
|
| 199 |
+
|
| 200 |
+
You may not remove or alter the substance of any license notices
|
| 201 |
+
(including copyright notices, patent notices, disclaimers of warranty,
|
| 202 |
+
or limitations of liability) contained within the Source Code Form of
|
| 203 |
+
the Covered Software, except that You may alter any license notices to
|
| 204 |
+
the extent required to remedy known factual inaccuracies.
|
| 205 |
+
|
| 206 |
+
3.5. Application of Additional Terms
|
| 207 |
+
|
| 208 |
+
You may choose to offer, and to charge a fee for, warranty, support,
|
| 209 |
+
indemnity or liability obligations to one or more recipients of Covered
|
| 210 |
+
Software. However, You may do so only on Your own behalf, and not on
|
| 211 |
+
behalf of any Contributor. You must make it absolutely clear that any
|
| 212 |
+
such warranty, support, indemnity, or liability obligation is offered by
|
| 213 |
+
You alone, and You hereby agree to indemnify every Contributor for any
|
| 214 |
+
liability incurred by such Contributor as a result of warranty, support,
|
| 215 |
+
indemnity or liability terms You offer. You may include additional
|
| 216 |
+
disclaimers of warranty and limitations of liability specific to any
|
| 217 |
+
jurisdiction.
|
| 218 |
+
|
| 219 |
+
4. Inability to Comply Due to Statute or Regulation
|
| 220 |
+
---------------------------------------------------
|
| 221 |
+
|
| 222 |
+
If it is impossible for You to comply with any of the terms of this
|
| 223 |
+
License with respect to some or all of the Covered Software due to
|
| 224 |
+
statute, judicial order, or regulation then You must: (a) comply with
|
| 225 |
+
the terms of this License to the maximum extent possible; and (b)
|
| 226 |
+
describe the limitations and the code they affect. Such description must
|
| 227 |
+
be placed in a text file included with all distributions of the Covered
|
| 228 |
+
Software under this License. Except to the extent prohibited by statute
|
| 229 |
+
or regulation, such description must be sufficiently detailed for a
|
| 230 |
+
recipient of ordinary skill to be able to understand it.
|
| 231 |
+
|
| 232 |
+
5. Termination
|
| 233 |
+
--------------
|
| 234 |
+
|
| 235 |
+
5.1. The rights granted under this License will terminate automatically
|
| 236 |
+
if You fail to comply with any of its terms. However, if You become
|
| 237 |
+
compliant, then the rights granted under this License from a particular
|
| 238 |
+
Contributor are reinstated (a) provisionally, unless and until such
|
| 239 |
+
Contributor explicitly and finally terminates Your grants, and (b) on an
|
| 240 |
+
ongoing basis, if such Contributor fails to notify You of the
|
| 241 |
+
non-compliance by some reasonable means prior to 60 days after You have
|
| 242 |
+
come back into compliance. Moreover, Your grants from a particular
|
| 243 |
+
Contributor are reinstated on an ongoing basis if such Contributor
|
| 244 |
+
notifies You of the non-compliance by some reasonable means, this is the
|
| 245 |
+
first time You have received notice of non-compliance with this License
|
| 246 |
+
from such Contributor, and You become compliant prior to 30 days after
|
| 247 |
+
Your receipt of the notice.
|
| 248 |
+
|
| 249 |
+
5.2. If You initiate litigation against any entity by asserting a patent
|
| 250 |
+
infringement claim (excluding declaratory judgment actions,
|
| 251 |
+
counter-claims, and cross-claims) alleging that a Contributor Version
|
| 252 |
+
directly or indirectly infringes any patent, then the rights granted to
|
| 253 |
+
You by any and all Contributors for the Covered Software under Section
|
| 254 |
+
2.1 of this License shall terminate.
|
| 255 |
+
|
| 256 |
+
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
|
| 257 |
+
end user license agreements (excluding distributors and resellers) which
|
| 258 |
+
have been validly granted by You or Your distributors under this License
|
| 259 |
+
prior to termination shall survive termination.
|
| 260 |
+
|
| 261 |
+
************************************************************************
|
| 262 |
+
* *
|
| 263 |
+
* 6. Disclaimer of Warranty *
|
| 264 |
+
* ------------------------- *
|
| 265 |
+
* *
|
| 266 |
+
* Covered Software is provided under this License on an "as is" *
|
| 267 |
+
* basis, without warranty of any kind, either expressed, implied, or *
|
| 268 |
+
* statutory, including, without limitation, warranties that the *
|
| 269 |
+
* Covered Software is free of defects, merchantable, fit for a *
|
| 270 |
+
* particular purpose or non-infringing. The entire risk as to the *
|
| 271 |
+
* quality and performance of the Covered Software is with You. *
|
| 272 |
+
* Should any Covered Software prove defective in any respect, You *
|
| 273 |
+
* (not any Contributor) assume the cost of any necessary servicing, *
|
| 274 |
+
* repair, or correction. This disclaimer of warranty constitutes an *
|
| 275 |
+
* essential part of this License. No use of any Covered Software is *
|
| 276 |
+
* authorized under this License except under this disclaimer. *
|
| 277 |
+
* *
|
| 278 |
+
************************************************************************
|
| 279 |
+
|
| 280 |
+
************************************************************************
|
| 281 |
+
* *
|
| 282 |
+
* 7. Limitation of Liability *
|
| 283 |
+
* -------------------------- *
|
| 284 |
+
* *
|
| 285 |
+
* Under no circumstances and under no legal theory, whether tort *
|
| 286 |
+
* (including negligence), contract, or otherwise, shall any *
|
| 287 |
+
* Contributor, or anyone who distributes Covered Software as *
|
| 288 |
+
* permitted above, be liable to You for any direct, indirect, *
|
| 289 |
+
* special, incidental, or consequential damages of any character *
|
| 290 |
+
* including, without limitation, damages for lost profits, loss of *
|
| 291 |
+
* goodwill, work stoppage, computer failure or malfunction, or any *
|
| 292 |
+
* and all other commercial damages or losses, even if such party *
|
| 293 |
+
* shall have been informed of the possibility of such damages. This *
|
| 294 |
+
* limitation of liability shall not apply to liability for death or *
|
| 295 |
+
* personal injury resulting from such party's negligence to the *
|
| 296 |
+
* extent applicable law prohibits such limitation. Some *
|
| 297 |
+
* jurisdictions do not allow the exclusion or limitation of *
|
| 298 |
+
* incidental or consequential damages, so this exclusion and *
|
| 299 |
+
* limitation may not apply to You. *
|
| 300 |
+
* *
|
| 301 |
+
************************************************************************
|
| 302 |
+
|
| 303 |
+
8. Litigation
|
| 304 |
+
-------------
|
| 305 |
+
|
| 306 |
+
Any litigation relating to this License may be brought only in the
|
| 307 |
+
courts of a jurisdiction where the defendant maintains its principal
|
| 308 |
+
place of business and such litigation shall be governed by laws of that
|
| 309 |
+
jurisdiction, without reference to its conflict-of-law provisions.
|
| 310 |
+
Nothing in this Section shall prevent a party's ability to bring
|
| 311 |
+
cross-claims or counter-claims.
|
| 312 |
+
|
| 313 |
+
9. Miscellaneous
|
| 314 |
+
----------------
|
| 315 |
+
|
| 316 |
+
This License represents the complete agreement concerning the subject
|
| 317 |
+
matter hereof. If any provision of this License is held to be
|
| 318 |
+
unenforceable, such provision shall be reformed only to the extent
|
| 319 |
+
necessary to make it enforceable. Any law or regulation which provides
|
| 320 |
+
that the language of a contract shall be construed against the drafter
|
| 321 |
+
shall not be used to construe this License against a Contributor.
|
| 322 |
+
|
| 323 |
+
10. Versions of the License
|
| 324 |
+
---------------------------
|
| 325 |
+
|
| 326 |
+
10.1. New Versions
|
| 327 |
+
|
| 328 |
+
Mozilla Foundation is the license steward. Except as provided in Section
|
| 329 |
+
10.3, no one other than the license steward has the right to modify or
|
| 330 |
+
publish new versions of this License. Each version will be given a
|
| 331 |
+
distinguishing version number.
|
| 332 |
+
|
| 333 |
+
10.2. Effect of New Versions
|
| 334 |
+
|
| 335 |
+
You may distribute the Covered Software under the terms of the version
|
| 336 |
+
of the License under which You originally received the Covered Software,
|
| 337 |
+
or under the terms of any subsequent version published by the license
|
| 338 |
+
steward.
|
| 339 |
+
|
| 340 |
+
10.3. Modified Versions
|
| 341 |
+
|
| 342 |
+
If you create software not governed by this License, and you want to
|
| 343 |
+
create a new license for such software, you may create and use a
|
| 344 |
+
modified version of this License if you rename the license and remove
|
| 345 |
+
any references to the name of the license steward (except to note that
|
| 346 |
+
such modified license differs from this License).
|
| 347 |
+
|
| 348 |
+
10.4. Distributing Source Code Form that is Incompatible With Secondary
|
| 349 |
+
Licenses
|
| 350 |
+
|
| 351 |
+
If You choose to distribute Source Code Form that is Incompatible With
|
| 352 |
+
Secondary Licenses under the terms of this version of the License, the
|
| 353 |
+
notice described in Exhibit B of this License must be attached.
|
| 354 |
+
|
| 355 |
+
Exhibit A - Source Code Form License Notice
|
| 356 |
+
-------------------------------------------
|
| 357 |
+
|
| 358 |
+
This Source Code Form is subject to the terms of the Mozilla Public
|
| 359 |
+
License, v. 2.0. If a copy of the MPL was not distributed with this
|
| 360 |
+
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
| 361 |
+
|
| 362 |
+
If it is not possible or desirable to put the notice in a particular
|
| 363 |
+
file, then You may include the notice in a location (such as a LICENSE
|
| 364 |
+
file in a relevant directory) where a recipient would be likely to look
|
| 365 |
+
for such a notice.
|
| 366 |
+
|
| 367 |
+
You may add additional accurate notices of copyright ownership.
|
| 368 |
+
|
| 369 |
+
Exhibit B - "Incompatible With Secondary Licenses" Notice
|
| 370 |
+
---------------------------------------------------------
|
| 371 |
+
|
| 372 |
+
This Source Code Form is "Incompatible With Secondary Licenses", as
|
| 373 |
+
defined by the Mozilla Public License, v. 2.0.
|
src/evalatin2024-latinpipe/README.md
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ÚFAL LatinPipe at EvaLatin 2024: Morphosyntactic Analysis of Latin
|
| 2 |
+
|
| 3 |
+
This repository contains the LatinPipe parser implementation described in
|
| 4 |
+
the _ÚFAL LatinPipe at EvaLatin 2024: Morphosyntactic Analysis of Latin_ paper.
|
| 5 |
+
|
| 6 |
+
📢 Besides this source code and the [trained model](https://hdl.handle.net/11234/1-5671),
|
| 7 |
+
LatinPipe is also available in the [UDPipe LINDAT/CLARIN service](http://lindat.mff.cuni.cz/services/udpipe/)
|
| 8 |
+
and can be used either in a web form or through a REST service.
|
| 9 |
+
|
| 10 |
+
---
|
| 11 |
+
|
| 12 |
+
<img src="figures/LatinPipe.svg" alt="LatinPipe Architecture" align="right" style="width: 45%">
|
| 13 |
+
|
| 14 |
+
<h3 align="center"><a href="https://aclanthology.org/2024.lt4hala-1.24/">ÚFAL LatinPipe at EvaLatin 2024: Morphosyntactic Analysis of Latin</a></h3>
|
| 15 |
+
|
| 16 |
+
<p align="center">
|
| 17 |
+
<b>Milan Straka</b> and <b>Jana Straková</b> and <b>Federica Gamba</b><br>
|
| 18 |
+
Charles University<br>
|
| 19 |
+
Faculty of Mathematics and Physics<br>
|
| 20 |
+
Institute of Formal and Applied Lingustics<br>
|
| 21 |
+
Malostranské nám. 25, Prague, Czech Republic
|
| 22 |
+
</p>
|
| 23 |
+
|
| 24 |
+
**Abstract:** We present LatinPipe, the winning submission to the EvaLatin 2024
|
| 25 |
+
Dependency Parsing shared task. Our system consists of a fine-tuned
|
| 26 |
+
concatenation of base and large pre-trained LMs, with a dot-product attention
|
| 27 |
+
head for parsing and softmax classification heads for morphology to jointly
|
| 28 |
+
learn both dependency parsing and morphological analysis. It is trained by
|
| 29 |
+
sampling from seven publicly available Latin corpora, utilizing additional
|
| 30 |
+
harmonization of annotations to achieve a more unified annotation style. Before
|
| 31 |
+
fine-tuning, we train the system for a few initial epochs with frozen weights.
|
| 32 |
+
We also add additional local relative contextualization by stacking the BiLSTM
|
| 33 |
+
layers on top of the Transformer(s). Finally, we ensemble output probability
|
| 34 |
+
distributions from seven randomly instantiated networks for the final
|
| 35 |
+
submission. The code is available at <a href="https://github.com/ufal/evalatin2024-latinpipe">https://github.com/ufal/evalatin2024-latinpipe</a>.<br clear="both">
|
| 36 |
+
|
| 37 |
+
---
|
| 38 |
+
|
| 39 |
+
## Content of this Repository
|
| 40 |
+
|
| 41 |
+
- The directory `data` is for all the required data (UD 2.13 data, harmonized
|
| 42 |
+
PROIEL, Sabellicus, Archimedes Latinus, EvaLatin 2024 test data).
|
| 43 |
+
- The script `data/fetch_data.sh` downloads and extracts all the data:
|
| 44 |
+
```sh
|
| 45 |
+
(cd data && sh fetch_data.sh)
|
| 46 |
+
```
|
| 47 |
+
|
| 48 |
+
- The `latinpipe_evalatin24.py` is the LatinPipe EvaLatin24 source.
|
| 49 |
+
- It depends on `latinpipe_evalatin24_eval.py`, which is a modularized version
|
| 50 |
+
of the official evaluation script.
|
| 51 |
+
|
| 52 |
+
- The `latinpipe_evalatin24_server.py` is a REST server with UDPipe-2-compatible
|
| 53 |
+
API, using `latinpipe_evalatin24.py` to perform tagging and parsing.
|
| 54 |
+
|
| 55 |
+
## The Released `latinpipe-evalatin24-240520` Model
|
| 56 |
+
|
| 57 |
+
The `latinpipe-evalatin24-240520` is a `PhilBerta`-based model for tagging,
|
| 58 |
+
lemmatization, and dependency parsing of Latin, based on the winning entry
|
| 59 |
+
to the EvaLatin 2024 <https://circse.github.io/LT4HALA/2024/EvaLatin> shared
|
| 60 |
+
task. It is released at https://hdl.handle.net/11234/1-5671 under the CC
|
| 61 |
+
BY-NC-SA 4.0 license.
|
| 62 |
+
|
| 63 |
+
The model is also available in the [UDPipe LINDAT/CLARIN service](http://lindat.mff.cuni.cz/services/udpipe/)
|
| 64 |
+
and can be used either in a web form or through a REST service.
|
| 65 |
+
|
| 66 |
+
See the [latinpipe-evalatin24-240520 directory](latinpipe-evalatin24-240520/) for
|
| 67 |
+
the download link, the model performance, and additional information.
|
| 68 |
+
|
| 69 |
+
## Training a Model
|
| 70 |
+
|
| 71 |
+
To train a model on all data, you should
|
| 72 |
+
1. run the `data/fetch_data.sh` script to download all required data,
|
| 73 |
+
2. create a Python environments with the packages listed in `requirements.txt`,
|
| 74 |
+
3. train the model itself using the `latinpipe_evalatin24.py` script.
|
| 75 |
+
|
| 76 |
+
To train a model performing UPOS/UFeats tagging, lemmatization, and
|
| 77 |
+
dependency parsing, we use
|
| 78 |
+
```sh
|
| 79 |
+
la_ud213_all="la_ittb la_llct la_perseus la_proiel la_udante"
|
| 80 |
+
la_other="la_archimedes la_sabellicus"
|
| 81 |
+
transformer="bowphs/PhilBerta" # or bowphs/LaBerta
|
| 82 |
+
|
| 83 |
+
latinpipe_evalatin24.py $(for split in dev test train; do echo --$split; for tb in $la_ud213_all; do [ $tb-$split = la_proiel-train ] && tb=la_proielh; echo data/$tb/$tb-ud-$split.conllu; done; done) $(for tb in $la_other; do echo data/$tb/$tb-train.conllu; done) --transformers $transformer --epochs=30 --exp=evalatin24_model --subword_combination=last --epochs_frozen=10 --batch_size=64 --save_checkpoint
|
| 84 |
+
```
|
| 85 |
+
|
| 86 |
+
## Predicting with a Trained Model
|
| 87 |
+
|
| 88 |
+
To predict with a trained model, you can use the following command:
|
| 89 |
+
```sh
|
| 90 |
+
latinpipe_evalatin24.py --load evalatin24_model/model.weights.h5 --exp target_directory --test input1.conllu input2.conllu
|
| 91 |
+
```
|
| 92 |
+
- the outputs are generated in the target directory, with a `.predicted.conllu` suffix;
|
| 93 |
+
- if you want to also evaluate the predicted files, you can use `--dev` option instead of `--test`.
|
| 94 |
+
|
| 95 |
+
---
|
| 96 |
+
|
| 97 |
+
## Contact
|
| 98 |
+
|
| 99 |
+
Milan Straka: ``[email protected]``\
|
| 100 |
+
Jana Straková: ``[email protected]``\
|
| 101 |
+
Federica Gamba: ``[email protected]``
|
| 102 |
+
|
| 103 |
+
## How to Cite
|
| 104 |
+
|
| 105 |
+
```
|
| 106 |
+
@inproceedings{straka-etal-2024-ufal,
|
| 107 |
+
title = "{{\'U}FAL} {L}atin{P}ipe at {E}va{L}atin 2024: Morphosyntactic Analysis of {L}atin",
|
| 108 |
+
author = "Straka, Milan and Strakov{\'a}, Jana and Gamba, Federica",
|
| 109 |
+
editor = "Sprugnoli, Rachele and Passarotti, Marco",
|
| 110 |
+
booktitle = "Proceedings of the Third Workshop on Language Technologies for Historical and Ancient Languages (LT4HALA) @ LREC-COLING-2024",
|
| 111 |
+
month = may,
|
| 112 |
+
year = "2024",
|
| 113 |
+
address = "Torino, Italia",
|
| 114 |
+
publisher = "ELRA and ICCL",
|
| 115 |
+
url = "https://aclanthology.org/2024.lt4hala-1.24",
|
| 116 |
+
pages = "207--214"
|
| 117 |
+
}
|
| 118 |
+
```
|
src/evalatin2024-latinpipe/__pycache__/latinpipe_evalatin24_eval.cpython-311.pyc
ADDED
|
Binary file (37.2 kB). View file
|
|
|
src/evalatin2024-latinpipe/data/conllu_split.py
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
#
|
| 3 |
+
# This file is part of LatinPipe EvaLatin 24
|
| 4 |
+
# <https://github.com/ufal/evalatin2024-latinpipe>.
|
| 5 |
+
#
|
| 6 |
+
# Copyright 2024 Institute of Formal and Applied Linguistics, Faculty of
|
| 7 |
+
# Mathematics and Physics, Charles University in Prague, Czech Republic.
|
| 8 |
+
#
|
| 9 |
+
# This Source Code Form is subject to the terms of the Mozilla Public
|
| 10 |
+
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
| 11 |
+
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
| 12 |
+
import argparse
|
| 13 |
+
|
| 14 |
+
import numpy as np
|
| 15 |
+
|
| 16 |
+
if __name__ == "__main__":
|
| 17 |
+
parser = argparse.ArgumentParser()
|
| 18 |
+
parser.add_argument("source", type=str, help="CoNLL-U file to split")
|
| 19 |
+
parser.add_argument("train", type=str, help="CoNLL-U file to write training data to")
|
| 20 |
+
parser.add_argument("dev", type=str, help="CoNLL-U file to write development data to")
|
| 21 |
+
parser.add_argument("--dev_size", type=float, default=0.1, help="Size of the development data")
|
| 22 |
+
args = parser.parse_args()
|
| 23 |
+
|
| 24 |
+
sentences = []
|
| 25 |
+
with open(args.source, "r", encoding="utf-8") as source:
|
| 26 |
+
sentence = []
|
| 27 |
+
for line in source:
|
| 28 |
+
sentence.append(line)
|
| 29 |
+
if not line.rstrip("\r\n"):
|
| 30 |
+
sentences.append("".join(sentence))
|
| 31 |
+
sentence = []
|
| 32 |
+
assert not sentence, "Missing empty line after the last sentence"
|
| 33 |
+
|
| 34 |
+
dev_indices = set(np.random.RandomState(42).choice(len(sentences), int(len(sentences) * args.dev_size), replace=False))
|
| 35 |
+
|
| 36 |
+
with open(args.train, "w", encoding="utf-8") as train:
|
| 37 |
+
with open(args.dev, "w", encoding="utf-8") as dev:
|
| 38 |
+
for i, sentence in enumerate(sentences):
|
| 39 |
+
(dev if i in dev_indices else train).write(sentence)
|
src/evalatin2024-latinpipe/data/fetch_data.sh
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/bin/bash
|
| 2 |
+
#
|
| 3 |
+
# This file is part of LatinPipe EvaLatin 24
|
| 4 |
+
# <https://github.com/ufal/evalatin2024-latinpipe>.
|
| 5 |
+
#
|
| 6 |
+
# Copyright 2024 Institute of Formal and Applied Linguistics, Faculty of
|
| 7 |
+
# Mathematics and Physics, Charles University in Prague, Czech Republic.
|
| 8 |
+
#
|
| 9 |
+
# This Source Code Form is subject to the terms of the Mozilla Public
|
| 10 |
+
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
| 11 |
+
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
| 12 |
+
|
| 13 |
+
# Refresh conllu_to_text.pl
|
| 14 |
+
curl -O https://raw.githubusercontent.com/UniversalDependencies/tools/master/conllu_to_text.pl
|
| 15 |
+
|
| 16 |
+
# Get the UD 2.13 data
|
| 17 |
+
curl -O https://lindat.mff.cuni.cz/repository/xmlui/bitstream/handle/11234/1-5287/ud-treebanks-v2.13.tgz
|
| 18 |
+
tar xf ud-treebanks-v2.13.tgz
|
| 19 |
+
|
| 20 |
+
for tb in ud-treebanks-v2.13/*Latin*/*-ud-train.conllu; do
|
| 21 |
+
dir=`dirname $tb`
|
| 22 |
+
long_name=`basename $dir`
|
| 23 |
+
code=`basename $tb`
|
| 24 |
+
code=${code%%-*}
|
| 25 |
+
echo Fetching $long_name as $code
|
| 26 |
+
|
| 27 |
+
mkdir -p $code
|
| 28 |
+
cp $dir/* $code
|
| 29 |
+
if [ ! -f $code/$code-ud-dev.conllu ]; then
|
| 30 |
+
python3 conllu_split.py $dir/$code-ud-train.conllu $code/$code-ud-train.conllu $code/$code-ud-dev.conllu
|
| 31 |
+
for conllu in $code/$code-ud-train.conllu $code/$code-ud-dev.conllu; do
|
| 32 |
+
perl conllu_to_text.pl --language=$code <$conllu >${conllu%.conllu}.txt
|
| 33 |
+
done
|
| 34 |
+
fi
|
| 35 |
+
done
|
| 36 |
+
rm -rf ud-treebanks-v2.13.tgz ud-treebanks-v2.13/
|
| 37 |
+
|
| 38 |
+
for dir in */; do
|
| 39 |
+
echo "${dir%/} $(grep -cP "^\d+\t" $dir*train.conllu)"
|
| 40 |
+
done | sort -rnk2 >langs_sizes
|
| 41 |
+
|
| 42 |
+
# Get the non-UD small datasets
|
| 43 |
+
corpus=la_sabellicus
|
| 44 |
+
echo Fetching $corpus
|
| 45 |
+
mkdir -p $corpus
|
| 46 |
+
wget https://raw.githubusercontent.com/CIRCSE/Sabellicus/main/Sabellicus_DeLatinaeLinguaeReparatione.conllu -O $corpus/$corpus-train.conllu
|
| 47 |
+
|
| 48 |
+
corpus=la_archimedes
|
| 49 |
+
echo Fetching $corpus
|
| 50 |
+
mkdir -p $corpus
|
| 51 |
+
wget https://raw.githubusercontent.com/mfantoli/ArchimedesLatinus/main/training_data_final_git.conllu -O $corpus/tmp1.conllu
|
| 52 |
+
wget https://raw.githubusercontent.com/mfantoli/ArchimedesLatinus/main/spirals_XIX_XX_test_git.conllu -O $corpus/tmp2.conllu
|
| 53 |
+
cat $corpus/tmp1.conllu $corpus/tmp2.conllu > $corpus/$corpus-train.conllu
|
| 54 |
+
rm $corpus/tmp1.conllu $corpus/tmp2.conllu
|
| 55 |
+
|
| 56 |
+
# Get the test data
|
| 57 |
+
wget https://github.com/CIRCSE/LT4HALA/raw/db51eaa114f437ac5c6cc04e802fc50cbd8b9f67/2024/data_and_doc/EvaLatin_2024_Syntactic_Parsing_test_data.zip
|
| 58 |
+
mkdir -p evalatin24
|
| 59 |
+
unzip -j EvaLatin_2024_Syntactic_Parsing_test_data.zip -d evalatin24/ -x "*/.*"
|
| 60 |
+
rm EvaLatin_2024_Syntactic_Parsing_test_data.zip
|
| 61 |
+
|
| 62 |
+
# Get harmonized PROIEL
|
| 63 |
+
mkdir -p la_proielh/
|
| 64 |
+
for split in train dev test; do
|
| 65 |
+
wget https://github.com/fjambe/Latin-variability/raw/98f676c8a4575aee24c66fee73a09aecbe515643/morpho_harmonization/morpho-harmonized-treebanks/UD_Latin-PROIEL/MM-la_proiel-ud-$split.conllu -O la_proielh/la_proielh-ud-$split.conllu
|
| 66 |
+
done
|
src/evalatin2024-latinpipe/figures/LatinPipe.svg
ADDED
|
|
src/evalatin2024-latinpipe/latinpipe-evalatin24-240520/LICENSE
ADDED
|
@@ -0,0 +1,435 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Attribution-NonCommercial-ShareAlike 4.0 International
|
| 2 |
+
|
| 3 |
+
=======================================================================
|
| 4 |
+
|
| 5 |
+
Creative Commons Corporation ("Creative Commons") is not a law firm and
|
| 6 |
+
does not provide legal services or legal advice. Distribution of
|
| 7 |
+
Creative Commons public licenses does not create a lawyer-client or
|
| 8 |
+
other relationship. Creative Commons makes its licenses and related
|
| 9 |
+
information available on an "as-is" basis. Creative Commons gives no
|
| 10 |
+
warranties regarding its licenses, any material licensed under their
|
| 11 |
+
terms and conditions, or any related information. Creative Commons
|
| 12 |
+
disclaims all liability for damages resulting from their use to the
|
| 13 |
+
fullest extent possible.
|
| 14 |
+
|
| 15 |
+
Using Creative Commons Public Licenses
|
| 16 |
+
|
| 17 |
+
Creative Commons public licenses provide a standard set of terms and
|
| 18 |
+
conditions that creators and other rights holders may use to share
|
| 19 |
+
original works of authorship and other material subject to copyright
|
| 20 |
+
and certain other rights specified in the public license below. The
|
| 21 |
+
following considerations are for informational purposes only, are not
|
| 22 |
+
exhaustive, and do not form part of our licenses.
|
| 23 |
+
|
| 24 |
+
Considerations for licensors: Our public licenses are
|
| 25 |
+
intended for use by those authorized to give the public
|
| 26 |
+
permission to use material in ways otherwise restricted by
|
| 27 |
+
copyright and certain other rights. Our licenses are
|
| 28 |
+
irrevocable. Licensors should read and understand the terms
|
| 29 |
+
and conditions of the license they choose before applying it.
|
| 30 |
+
Licensors should also secure all rights necessary before
|
| 31 |
+
applying our licenses so that the public can reuse the
|
| 32 |
+
material as expected. Licensors should clearly mark any
|
| 33 |
+
material not subject to the license. This includes other CC-
|
| 34 |
+
licensed material, or material used under an exception or
|
| 35 |
+
limitation to copyright. More considerations for licensors:
|
| 36 |
+
wiki.creativecommons.org/Considerations_for_licensors
|
| 37 |
+
|
| 38 |
+
Considerations for the public: By using one of our public
|
| 39 |
+
licenses, a licensor grants the public permission to use the
|
| 40 |
+
licensed material under specified terms and conditions. If
|
| 41 |
+
the licensor's permission is not necessary for any reason--for
|
| 42 |
+
example, because of any applicable exception or limitation to
|
| 43 |
+
copyright--then that use is not regulated by the license. Our
|
| 44 |
+
licenses grant only permissions under copyright and certain
|
| 45 |
+
other rights that a licensor has authority to grant. Use of
|
| 46 |
+
the licensed material may still be restricted for other
|
| 47 |
+
reasons, including because others have copyright or other
|
| 48 |
+
rights in the material. A licensor may make special requests,
|
| 49 |
+
such as asking that all changes be marked or described.
|
| 50 |
+
Although not required by our licenses, you are encouraged to
|
| 51 |
+
respect those requests where reasonable. More_considerations
|
| 52 |
+
for the public:
|
| 53 |
+
wiki.creativecommons.org/Considerations_for_licensees
|
| 54 |
+
|
| 55 |
+
=======================================================================
|
| 56 |
+
|
| 57 |
+
Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International
|
| 58 |
+
Public License
|
| 59 |
+
|
| 60 |
+
By exercising the Licensed Rights (defined below), You accept and agree
|
| 61 |
+
to be bound by the terms and conditions of this Creative Commons
|
| 62 |
+
Attribution-NonCommercial-ShareAlike 4.0 International Public License
|
| 63 |
+
("Public License"). To the extent this Public License may be
|
| 64 |
+
interpreted as a contract, You are granted the Licensed Rights in
|
| 65 |
+
consideration of Your acceptance of these terms and conditions, and the
|
| 66 |
+
Licensor grants You such rights in consideration of benefits the
|
| 67 |
+
Licensor receives from making the Licensed Material available under
|
| 68 |
+
these terms and conditions.
|
| 69 |
+
|
| 70 |
+
|
| 71 |
+
Section 1 -- Definitions.
|
| 72 |
+
|
| 73 |
+
a. Adapted Material means material subject to Copyright and Similar
|
| 74 |
+
Rights that is derived from or based upon the Licensed Material
|
| 75 |
+
and in which the Licensed Material is translated, altered,
|
| 76 |
+
arranged, transformed, or otherwise modified in a manner requiring
|
| 77 |
+
permission under the Copyright and Similar Rights held by the
|
| 78 |
+
Licensor. For purposes of this Public License, where the Licensed
|
| 79 |
+
Material is a musical work, performance, or sound recording,
|
| 80 |
+
Adapted Material is always produced where the Licensed Material is
|
| 81 |
+
synched in timed relation with a moving image.
|
| 82 |
+
|
| 83 |
+
b. Adapter's License means the license You apply to Your Copyright
|
| 84 |
+
and Similar Rights in Your contributions to Adapted Material in
|
| 85 |
+
accordance with the terms and conditions of this Public License.
|
| 86 |
+
|
| 87 |
+
c. BY-NC-SA Compatible License means a license listed at
|
| 88 |
+
creativecommons.org/compatiblelicenses, approved by Creative
|
| 89 |
+
Commons as essentially the equivalent of this Public License.
|
| 90 |
+
|
| 91 |
+
d. Copyright and Similar Rights means copyright and/or similar rights
|
| 92 |
+
closely related to copyright including, without limitation,
|
| 93 |
+
performance, broadcast, sound recording, and Sui Generis Database
|
| 94 |
+
Rights, without regard to how the rights are labeled or
|
| 95 |
+
categorized. For purposes of this Public License, the rights
|
| 96 |
+
specified in Section 2(b)(1)-(2) are not Copyright and Similar
|
| 97 |
+
Rights.
|
| 98 |
+
|
| 99 |
+
e. Effective Technological Measures means those measures that, in the
|
| 100 |
+
absence of proper authority, may not be circumvented under laws
|
| 101 |
+
fulfilling obligations under Article 11 of the WIPO Copyright
|
| 102 |
+
Treaty adopted on December 20, 1996, and/or similar international
|
| 103 |
+
agreements.
|
| 104 |
+
|
| 105 |
+
f. Exceptions and Limitations means fair use, fair dealing, and/or
|
| 106 |
+
any other exception or limitation to Copyright and Similar Rights
|
| 107 |
+
that applies to Your use of the Licensed Material.
|
| 108 |
+
|
| 109 |
+
g. License Elements means the license attributes listed in the name
|
| 110 |
+
of a Creative Commons Public License. The License Elements of this
|
| 111 |
+
Public License are Attribution, NonCommercial, and ShareAlike.
|
| 112 |
+
|
| 113 |
+
h. Licensed Material means the artistic or literary work, database,
|
| 114 |
+
or other material to which the Licensor applied this Public
|
| 115 |
+
License.
|
| 116 |
+
|
| 117 |
+
i. Licensed Rights means the rights granted to You subject to the
|
| 118 |
+
terms and conditions of this Public License, which are limited to
|
| 119 |
+
all Copyright and Similar Rights that apply to Your use of the
|
| 120 |
+
Licensed Material and that the Licensor has authority to license.
|
| 121 |
+
|
| 122 |
+
j. Licensor means the individual(s) or entity(ies) granting rights
|
| 123 |
+
under this Public License.
|
| 124 |
+
|
| 125 |
+
k. NonCommercial means not primarily intended for or directed towards
|
| 126 |
+
commercial advantage or monetary compensation. For purposes of
|
| 127 |
+
this Public License, the exchange of the Licensed Material for
|
| 128 |
+
other material subject to Copyright and Similar Rights by digital
|
| 129 |
+
file-sharing or similar means is NonCommercial provided there is
|
| 130 |
+
no payment of monetary compensation in connection with the
|
| 131 |
+
exchange.
|
| 132 |
+
|
| 133 |
+
l. Share means to provide material to the public by any means or
|
| 134 |
+
process that requires permission under the Licensed Rights, such
|
| 135 |
+
as reproduction, public display, public performance, distribution,
|
| 136 |
+
dissemination, communication, or importation, and to make material
|
| 137 |
+
available to the public including in ways that members of the
|
| 138 |
+
public may access the material from a place and at a time
|
| 139 |
+
individually chosen by them.
|
| 140 |
+
|
| 141 |
+
m. Sui Generis Database Rights means rights other than copyright
|
| 142 |
+
resulting from Directive 96/9/EC of the European Parliament and of
|
| 143 |
+
the Council of 11 March 1996 on the legal protection of databases,
|
| 144 |
+
as amended and/or succeeded, as well as other essentially
|
| 145 |
+
equivalent rights anywhere in the world.
|
| 146 |
+
|
| 147 |
+
n. You means the individual or entity exercising the Licensed Rights
|
| 148 |
+
under this Public License. Your has a corresponding meaning.
|
| 149 |
+
|
| 150 |
+
|
| 151 |
+
Section 2 -- Scope.
|
| 152 |
+
|
| 153 |
+
a. License grant.
|
| 154 |
+
|
| 155 |
+
1. Subject to the terms and conditions of this Public License,
|
| 156 |
+
the Licensor hereby grants You a worldwide, royalty-free,
|
| 157 |
+
non-sublicensable, non-exclusive, irrevocable license to
|
| 158 |
+
exercise the Licensed Rights in the Licensed Material to:
|
| 159 |
+
|
| 160 |
+
a. reproduce and Share the Licensed Material, in whole or
|
| 161 |
+
in part, for NonCommercial purposes only; and
|
| 162 |
+
|
| 163 |
+
b. produce, reproduce, and Share Adapted Material for
|
| 164 |
+
NonCommercial purposes only.
|
| 165 |
+
|
| 166 |
+
2. Exceptions and Limitations. For the avoidance of doubt, where
|
| 167 |
+
Exceptions and Limitations apply to Your use, this Public
|
| 168 |
+
License does not apply, and You do not need to comply with
|
| 169 |
+
its terms and conditions.
|
| 170 |
+
|
| 171 |
+
3. Term. The term of this Public License is specified in Section
|
| 172 |
+
6(a).
|
| 173 |
+
|
| 174 |
+
4. Media and formats; technical modifications allowed. The
|
| 175 |
+
Licensor authorizes You to exercise the Licensed Rights in
|
| 176 |
+
all media and formats whether now known or hereafter created,
|
| 177 |
+
and to make technical modifications necessary to do so. The
|
| 178 |
+
Licensor waives and/or agrees not to assert any right or
|
| 179 |
+
authority to forbid You from making technical modifications
|
| 180 |
+
necessary to exercise the Licensed Rights, including
|
| 181 |
+
technical modifications necessary to circumvent Effective
|
| 182 |
+
Technological Measures. For purposes of this Public License,
|
| 183 |
+
simply making modifications authorized by this Section 2(a)
|
| 184 |
+
(4) never produces Adapted Material.
|
| 185 |
+
|
| 186 |
+
5. Downstream recipients.
|
| 187 |
+
|
| 188 |
+
a. Offer from the Licensor -- Licensed Material. Every
|
| 189 |
+
recipient of the Licensed Material automatically
|
| 190 |
+
receives an offer from the Licensor to exercise the
|
| 191 |
+
Licensed Rights under the terms and conditions of this
|
| 192 |
+
Public License.
|
| 193 |
+
|
| 194 |
+
b. Additional offer from the Licensor -- Adapted Material.
|
| 195 |
+
Every recipient of Adapted Material from You
|
| 196 |
+
automatically receives an offer from the Licensor to
|
| 197 |
+
exercise the Licensed Rights in the Adapted Material
|
| 198 |
+
under the conditions of the Adapter's License You apply.
|
| 199 |
+
|
| 200 |
+
c. No downstream restrictions. You may not offer or impose
|
| 201 |
+
any additional or different terms or conditions on, or
|
| 202 |
+
apply any Effective Technological Measures to, the
|
| 203 |
+
Licensed Material if doing so restricts exercise of the
|
| 204 |
+
Licensed Rights by any recipient of the Licensed
|
| 205 |
+
Material.
|
| 206 |
+
|
| 207 |
+
6. No endorsement. Nothing in this Public License constitutes or
|
| 208 |
+
may be construed as permission to assert or imply that You
|
| 209 |
+
are, or that Your use of the Licensed Material is, connected
|
| 210 |
+
with, or sponsored, endorsed, or granted official status by,
|
| 211 |
+
the Licensor or others designated to receive attribution as
|
| 212 |
+
provided in Section 3(a)(1)(A)(i).
|
| 213 |
+
|
| 214 |
+
b. Other rights.
|
| 215 |
+
|
| 216 |
+
1. Moral rights, such as the right of integrity, are not
|
| 217 |
+
licensed under this Public License, nor are publicity,
|
| 218 |
+
privacy, and/or other similar personality rights; however, to
|
| 219 |
+
the extent possible, the Licensor waives and/or agrees not to
|
| 220 |
+
assert any such rights held by the Licensor to the limited
|
| 221 |
+
extent necessary to allow You to exercise the Licensed
|
| 222 |
+
Rights, but not otherwise.
|
| 223 |
+
|
| 224 |
+
2. Patent and trademark rights are not licensed under this
|
| 225 |
+
Public License.
|
| 226 |
+
|
| 227 |
+
3. To the extent possible, the Licensor waives any right to
|
| 228 |
+
collect royalties from You for the exercise of the Licensed
|
| 229 |
+
Rights, whether directly or through a collecting society
|
| 230 |
+
under any voluntary or waivable statutory or compulsory
|
| 231 |
+
licensing scheme. In all other cases the Licensor expressly
|
| 232 |
+
reserves any right to collect such royalties, including when
|
| 233 |
+
the Licensed Material is used other than for NonCommercial
|
| 234 |
+
purposes.
|
| 235 |
+
|
| 236 |
+
|
| 237 |
+
Section 3 -- License Conditions.
|
| 238 |
+
|
| 239 |
+
Your exercise of the Licensed Rights is expressly made subject to the
|
| 240 |
+
following conditions.
|
| 241 |
+
|
| 242 |
+
a. Attribution.
|
| 243 |
+
|
| 244 |
+
1. If You Share the Licensed Material (including in modified
|
| 245 |
+
form), You must:
|
| 246 |
+
|
| 247 |
+
a. retain the following if it is supplied by the Licensor
|
| 248 |
+
with the Licensed Material:
|
| 249 |
+
|
| 250 |
+
i. identification of the creator(s) of the Licensed
|
| 251 |
+
Material and any others designated to receive
|
| 252 |
+
attribution, in any reasonable manner requested by
|
| 253 |
+
the Licensor (including by pseudonym if
|
| 254 |
+
designated);
|
| 255 |
+
|
| 256 |
+
ii. a copyright notice;
|
| 257 |
+
|
| 258 |
+
iii. a notice that refers to this Public License;
|
| 259 |
+
|
| 260 |
+
iv. a notice that refers to the disclaimer of
|
| 261 |
+
warranties;
|
| 262 |
+
|
| 263 |
+
v. a URI or hyperlink to the Licensed Material to the
|
| 264 |
+
extent reasonably practicable;
|
| 265 |
+
|
| 266 |
+
b. indicate if You modified the Licensed Material and
|
| 267 |
+
retain an indication of any previous modifications; and
|
| 268 |
+
|
| 269 |
+
c. indicate the Licensed Material is licensed under this
|
| 270 |
+
Public License, and include the text of, or the URI or
|
| 271 |
+
hyperlink to, this Public License.
|
| 272 |
+
|
| 273 |
+
2. You may satisfy the conditions in Section 3(a)(1) in any
|
| 274 |
+
reasonable manner based on the medium, means, and context in
|
| 275 |
+
which You Share the Licensed Material. For example, it may be
|
| 276 |
+
reasonable to satisfy the conditions by providing a URI or
|
| 277 |
+
hyperlink to a resource that includes the required
|
| 278 |
+
information.
|
| 279 |
+
3. If requested by the Licensor, You must remove any of the
|
| 280 |
+
information required by Section 3(a)(1)(A) to the extent
|
| 281 |
+
reasonably practicable.
|
| 282 |
+
|
| 283 |
+
b. ShareAlike.
|
| 284 |
+
|
| 285 |
+
In addition to the conditions in Section 3(a), if You Share
|
| 286 |
+
Adapted Material You produce, the following conditions also apply.
|
| 287 |
+
|
| 288 |
+
1. The Adapter's License You apply must be a Creative Commons
|
| 289 |
+
license with the same License Elements, this version or
|
| 290 |
+
later, or a BY-NC-SA Compatible License.
|
| 291 |
+
|
| 292 |
+
2. You must include the text of, or the URI or hyperlink to, the
|
| 293 |
+
Adapter's License You apply. You may satisfy this condition
|
| 294 |
+
in any reasonable manner based on the medium, means, and
|
| 295 |
+
context in which You Share Adapted Material.
|
| 296 |
+
|
| 297 |
+
3. You may not offer or impose any additional or different terms
|
| 298 |
+
or conditions on, or apply any Effective Technological
|
| 299 |
+
Measures to, Adapted Material that restrict exercise of the
|
| 300 |
+
rights granted under the Adapter's License You apply.
|
| 301 |
+
|
| 302 |
+
|
| 303 |
+
Section 4 -- Sui Generis Database Rights.
|
| 304 |
+
|
| 305 |
+
Where the Licensed Rights include Sui Generis Database Rights that
|
| 306 |
+
apply to Your use of the Licensed Material:
|
| 307 |
+
|
| 308 |
+
a. for the avoidance of doubt, Section 2(a)(1) grants You the right
|
| 309 |
+
to extract, reuse, reproduce, and Share all or a substantial
|
| 310 |
+
portion of the contents of the database for NonCommercial purposes
|
| 311 |
+
only;
|
| 312 |
+
|
| 313 |
+
b. if You include all or a substantial portion of the database
|
| 314 |
+
contents in a database in which You have Sui Generis Database
|
| 315 |
+
Rights, then the database in which You have Sui Generis Database
|
| 316 |
+
Rights (but not its individual contents) is Adapted Material,
|
| 317 |
+
including for purposes of Section 3(b); and
|
| 318 |
+
|
| 319 |
+
c. You must comply with the conditions in Section 3(a) if You Share
|
| 320 |
+
all or a substantial portion of the contents of the database.
|
| 321 |
+
|
| 322 |
+
For the avoidance of doubt, this Section 4 supplements and does not
|
| 323 |
+
replace Your obligations under this Public License where the Licensed
|
| 324 |
+
Rights include other Copyright and Similar Rights.
|
| 325 |
+
|
| 326 |
+
|
| 327 |
+
Section 5 -- Disclaimer of Warranties and Limitation of Liability.
|
| 328 |
+
|
| 329 |
+
a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
|
| 330 |
+
EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
|
| 331 |
+
AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
|
| 332 |
+
ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
|
| 333 |
+
IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
|
| 334 |
+
WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
| 335 |
+
PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
|
| 336 |
+
ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
|
| 337 |
+
KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
|
| 338 |
+
ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
|
| 339 |
+
|
| 340 |
+
b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
|
| 341 |
+
TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
|
| 342 |
+
NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
|
| 343 |
+
INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
|
| 344 |
+
COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
|
| 345 |
+
USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
|
| 346 |
+
ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
|
| 347 |
+
DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
|
| 348 |
+
IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
|
| 349 |
+
|
| 350 |
+
c. The disclaimer of warranties and limitation of liability provided
|
| 351 |
+
above shall be interpreted in a manner that, to the extent
|
| 352 |
+
possible, most closely approximates an absolute disclaimer and
|
| 353 |
+
waiver of all liability.
|
| 354 |
+
|
| 355 |
+
|
| 356 |
+
Section 6 -- Term and Termination.
|
| 357 |
+
|
| 358 |
+
a. This Public License applies for the term of the Copyright and
|
| 359 |
+
Similar Rights licensed here. However, if You fail to comply with
|
| 360 |
+
this Public License, then Your rights under this Public License
|
| 361 |
+
terminate automatically.
|
| 362 |
+
|
| 363 |
+
b. Where Your right to use the Licensed Material has terminated under
|
| 364 |
+
Section 6(a), it reinstates:
|
| 365 |
+
|
| 366 |
+
1. automatically as of the date the violation is cured, provided
|
| 367 |
+
it is cured within 30 days of Your discovery of the
|
| 368 |
+
violation; or
|
| 369 |
+
|
| 370 |
+
2. upon express reinstatement by the Licensor.
|
| 371 |
+
|
| 372 |
+
For the avoidance of doubt, this Section 6(b) does not affect any
|
| 373 |
+
right the Licensor may have to seek remedies for Your violations
|
| 374 |
+
of this Public License.
|
| 375 |
+
|
| 376 |
+
c. For the avoidance of doubt, the Licensor may also offer the
|
| 377 |
+
Licensed Material under separate terms or conditions or stop
|
| 378 |
+
distributing the Licensed Material at any time; however, doing so
|
| 379 |
+
will not terminate this Public License.
|
| 380 |
+
|
| 381 |
+
d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
|
| 382 |
+
License.
|
| 383 |
+
|
| 384 |
+
|
| 385 |
+
Section 7 -- Other Terms and Conditions.
|
| 386 |
+
|
| 387 |
+
a. The Licensor shall not be bound by any additional or different
|
| 388 |
+
terms or conditions communicated by You unless expressly agreed.
|
| 389 |
+
|
| 390 |
+
b. Any arrangements, understandings, or agreements regarding the
|
| 391 |
+
Licensed Material not stated herein are separate from and
|
| 392 |
+
independent of the terms and conditions of this Public License.
|
| 393 |
+
|
| 394 |
+
|
| 395 |
+
Section 8 -- Interpretation.
|
| 396 |
+
|
| 397 |
+
a. For the avoidance of doubt, this Public License does not, and
|
| 398 |
+
shall not be interpreted to, reduce, limit, restrict, or impose
|
| 399 |
+
conditions on any use of the Licensed Material that could lawfully
|
| 400 |
+
be made without permission under this Public License.
|
| 401 |
+
|
| 402 |
+
b. To the extent possible, if any provision of this Public License is
|
| 403 |
+
deemed unenforceable, it shall be automatically reformed to the
|
| 404 |
+
minimum extent necessary to make it enforceable. If the provision
|
| 405 |
+
cannot be reformed, it shall be severed from this Public License
|
| 406 |
+
without affecting the enforceability of the remaining terms and
|
| 407 |
+
conditions.
|
| 408 |
+
|
| 409 |
+
c. No term or condition of this Public License will be waived and no
|
| 410 |
+
failure to comply consented to unless expressly agreed to by the
|
| 411 |
+
Licensor.
|
| 412 |
+
|
| 413 |
+
d. Nothing in this Public License constitutes or may be interpreted
|
| 414 |
+
as a limitation upon, or waiver of, any privileges and immunities
|
| 415 |
+
that apply to the Licensor or You, including from the legal
|
| 416 |
+
processes of any jurisdiction or authority.
|
| 417 |
+
|
| 418 |
+
=======================================================================
|
| 419 |
+
|
| 420 |
+
Creative Commons is not a party to its public licenses.
|
| 421 |
+
Notwithstanding, Creative Commons may elect to apply one of its public
|
| 422 |
+
licenses to material it publishes and in those instances will be
|
| 423 |
+
considered the "Licensor." Except for the limited purpose of indicating
|
| 424 |
+
that material is shared under a Creative Commons public license or as
|
| 425 |
+
otherwise permitted by the Creative Commons policies published at
|
| 426 |
+
creativecommons.org/policies, Creative Commons does not authorize the
|
| 427 |
+
use of the trademark "Creative Commons" or any other trademark or logo
|
| 428 |
+
of Creative Commons without its prior written consent including,
|
| 429 |
+
without limitation, in connection with any unauthorized modifications
|
| 430 |
+
to any of its public licenses or any other arrangements,
|
| 431 |
+
understandings, or agreements concerning use of licensed material. For
|
| 432 |
+
the avoidance of doubt, this paragraph does not form part of the public
|
| 433 |
+
licenses.
|
| 434 |
+
|
| 435 |
+
Creative Commons may be contacted at creativecommons.org.
|
src/evalatin2024-latinpipe/latinpipe-evalatin24-240520/README.md
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# The `latinpipe-evalatin24-240520` Model
|
| 2 |
+
|
| 3 |
+
The `latinpipe-evalatin24-240520` is a `PhilBerta`-based model for tagging,
|
| 4 |
+
lemmatization, and dependency parsing of Latin, based on the winning entry
|
| 5 |
+
to the EvaLatin 2024 <https://circse.github.io/LT4HALA/2024/EvaLatin> shared
|
| 6 |
+
task. It is released at https://hdl.handle.net/11234/1-5671 under the CC
|
| 7 |
+
BY-NC-SA 4.0 license.
|
| 8 |
+
|
| 9 |
+
The model is also available in the [UDPipe LINDAT/CLARIN service](http://lindat.mff.cuni.cz/services/udpipe/)
|
| 10 |
+
and can be used either in a web form or through a REST service.
|
| 11 |
+
|
| 12 |
+
The model was trained using the following command:
|
| 13 |
+
```sh
|
| 14 |
+
la_ud213_all="la_ittb la_llct la_perseus la_proiel la_udante"
|
| 15 |
+
la_other="la_archimedes la_sabellicus"
|
| 16 |
+
transformer="bowphs/PhilBerta" # or bowphs/LaBerta
|
| 17 |
+
|
| 18 |
+
latinpipe_evalatin24.py $(for split in dev test train; do echo --$split; for tb in $la_ud213_all; do [ $tb-$split = la_proiel-train ] && tb=la_proielh; echo data/$tb/$tb-ud-$split.conllu; done; done) $(for tb in $la_other; do echo data/$tb/$tb-train.conllu; done) --transformers $transformer --epochs=30 --exp=latinpipe-evalatin24-240520 --subword_combination=last --epochs_frozen=10 --batch_size=64 --save_checkpoint
|
| 19 |
+
```
|
| 20 |
+
|
| 21 |
+
## EvaLatin 2024 LAS Results
|
| 22 |
+
|
| 23 |
+
The model achieves the following EvaLatin 2024 results (measured by the
|
| 24 |
+
official scorer). Note that the results are worse than in the paper, where the
|
| 25 |
+
model used the gold POS tags and was ensembled.
|
| 26 |
+
|
| 27 |
+
Treebank | UAS | LAS |
|
| 28 |
+
:-------------------- |:-----:|:-----:|
|
| 29 |
+
EvaLatin 2024 Poetry | 78.31 | 72.36 |
|
| 30 |
+
EvaLatin 2024 Prose | 80.49 | 75.20 |
|
| 31 |
+
EvaLatin 2024 Average | 79.40 | 73.78 |
|
| 32 |
+
|
| 33 |
+
## UD 2.13 Results
|
| 34 |
+
|
| 35 |
+
The model achieves the following UPOS, UFeats, Lemmas, UAS, LAS metrics (as
|
| 36 |
+
measured by the official scorer) on the UD 2.13 test data. Note that the model
|
| 37 |
+
was trained on harmonized PROIEL, so we do not include the official PROIEL
|
| 38 |
+
treebank in the evaluation.
|
| 39 |
+
|
| 40 |
+
Treebank | UPOS | UFeats | Lemmas | UAS | LAS |
|
| 41 |
+
:--------|:-----:|:------:|:------:|:-----:|:-----:|
|
| 42 |
+
ITTB | 99.30 | 98.53 | 98.64 | 93.82 | 92.31 |
|
| 43 |
+
LLCT | 99.80 | 97.60 | 96.39 | 96.37 | 95.35 |
|
| 44 |
+
Perseus | 96.01 | 91.14 | 88.88 | 87.93 | 82.50 |
|
| 45 |
+
UDante | 93.73 | 89.27 | 87.76 | 83.97 | 78.67 |
|
| 46 |
+
|
| 47 |
+
## Predicting with the `latinpipe-evalatin24-240520` Model
|
| 48 |
+
|
| 49 |
+
To predict with the `latinpipe-evalatin24-240520` model, you can use the following command:
|
| 50 |
+
```sh
|
| 51 |
+
latinpipe_evalatin24.py --load latinpipe-evalatin24-240520/model.weights.h5 --exp target_directory --test input1.conllu input2.conllu
|
| 52 |
+
```
|
| 53 |
+
- the outputs are generated in the target directory, with a `.predicted.conllu` suffix;
|
| 54 |
+
- if you want to also evaluate the predicted files, you can use `--dev` option instead of `--test`.
|
| 55 |
+
|
| 56 |
+
## How to Cite
|
| 57 |
+
|
| 58 |
+
```
|
| 59 |
+
@inproceedings{straka-etal-2024-ufal,
|
| 60 |
+
title = "{{\'U}FAL} {L}atin{P}ipe at {E}va{L}atin 2024: Morphosyntactic Analysis of {L}atin",
|
| 61 |
+
author = "Straka, Milan and Strakov{\'a}, Jana and Gamba, Federica",
|
| 62 |
+
editor = "Sprugnoli, Rachele and Passarotti, Marco",
|
| 63 |
+
booktitle = "Proceedings of the Third Workshop on Language Technologies for Historical and Ancient Languages (LT4HALA) @ LREC-COLING-2024",
|
| 64 |
+
month = may,
|
| 65 |
+
year = "2024",
|
| 66 |
+
address = "Torino, Italia",
|
| 67 |
+
publisher = "ELRA and ICCL",
|
| 68 |
+
url = "https://aclanthology.org/2024.lt4hala-1.24",
|
| 69 |
+
pages = "207--214"
|
| 70 |
+
}
|
| 71 |
+
```
|
src/evalatin2024-latinpipe/latinpipe_evalatin24.py
ADDED
|
@@ -0,0 +1,944 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
#
|
| 3 |
+
# This file is part of LatinPipe EvaLatin 24
|
| 4 |
+
# <https://github.com/ufal/evalatin2024-latinpipe>.
|
| 5 |
+
#
|
| 6 |
+
# Copyright 2024 Institute of Formal and Applied Linguistics, Faculty of
|
| 7 |
+
# Mathematics and Physics, Charles University in Prague, Czech Republic.
|
| 8 |
+
#
|
| 9 |
+
# This Source Code Form is subject to the terms of the Mozilla Public
|
| 10 |
+
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
| 11 |
+
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
| 12 |
+
|
| 13 |
+
import argparse
|
| 14 |
+
import collections
|
| 15 |
+
import datetime
|
| 16 |
+
import difflib
|
| 17 |
+
import io
|
| 18 |
+
import json
|
| 19 |
+
import os
|
| 20 |
+
import pickle
|
| 21 |
+
import re
|
| 22 |
+
from typing import Self
|
| 23 |
+
os.environ.setdefault("KERAS_BACKEND", "torch")
|
| 24 |
+
|
| 25 |
+
import keras
|
| 26 |
+
import numpy as np
|
| 27 |
+
import torch
|
| 28 |
+
import transformers
|
| 29 |
+
import ufal.chu_liu_edmonds
|
| 30 |
+
|
| 31 |
+
import latinpipe_evalatin24_eval
|
| 32 |
+
|
| 33 |
+
parser = argparse.ArgumentParser()
|
| 34 |
+
parser.add_argument("--batch_size", default=32, type=int, help="Batch size.")
|
| 35 |
+
parser.add_argument("--deprel", default="full", choices=["full", "universal"], type=str, help="Deprel kind.")
|
| 36 |
+
parser.add_argument("--dev", default=[], nargs="+", type=str, help="Dev CoNLL-U files.")
|
| 37 |
+
parser.add_argument("--dropout", default=0.5, type=float, help="Dropout")
|
| 38 |
+
parser.add_argument("--embed_tags", default="", type=str, help="Tags to embed on input.")
|
| 39 |
+
parser.add_argument("--epochs", default=30, type=int, help="Number of epochs.")
|
| 40 |
+
parser.add_argument("--epochs_frozen", default=0, type=int, help="Number of epochs with frozen transformer.")
|
| 41 |
+
parser.add_argument("--exp", default=None, type=str, help="Experiment name.")
|
| 42 |
+
parser.add_argument("--label_smoothing", default=0.03, type=float, help="Label smoothing.")
|
| 43 |
+
parser.add_argument("--learning_rate", default=2e-5, type=float, help="Learning rate.")
|
| 44 |
+
parser.add_argument("--learning_rate_decay", default="cos", choices=["none", "cos"], type=str, help="Learning rate decay.")
|
| 45 |
+
parser.add_argument("--learning_rate_warmup", default=2_000, type=int, help="Number of warmup steps.")
|
| 46 |
+
parser.add_argument("--load", default=[], type=str, nargs="*", help="Path to load models from.")
|
| 47 |
+
parser.add_argument("--max_train_sentence_len", default=150, type=int, help="Max sentence subwords in training.")
|
| 48 |
+
parser.add_argument("--optimizer", default="adam", choices=["adam", "adafactor"], type=str, help="Optimizer.")
|
| 49 |
+
parser.add_argument("--parse", default=1, type=int, help="Parse.")
|
| 50 |
+
parser.add_argument("--parse_attention_dim", default=512, type=int, help="Parse attention dimension.")
|
| 51 |
+
parser.add_argument("--rnn_dim", default=512, type=int, help="RNN layers size.")
|
| 52 |
+
parser.add_argument("--rnn_layers", default=2, type=int, help="RNN layers.")
|
| 53 |
+
parser.add_argument("--rnn_type", default="LSTMTorch", choices=["LSTM", "GRU", "LSTMTorch", "GRUTorch"], help="RNN type.")
|
| 54 |
+
parser.add_argument("--save_checkpoint", default=False, action="store_true", help="Save checkpoint.")
|
| 55 |
+
parser.add_argument("--seed", default=42, type=int, help="Initial random seed.")
|
| 56 |
+
parser.add_argument("--steps_per_epoch", default=1_000, type=int, help="Steps per epoch.")
|
| 57 |
+
parser.add_argument("--single_root", default=1, type=int, help="Single root allowed only.")
|
| 58 |
+
parser.add_argument("--subword_combination", default="first", choices=["first", "last", "sum", "concat"], type=str, help="Subword combination.")
|
| 59 |
+
parser.add_argument("--tags", default="UPOS,LEMMAS,FEATS", type=str, help="Tags to predict.")
|
| 60 |
+
parser.add_argument("--task_hidden_layer", default=2_048, type=int, help="Task hidden layer size.")
|
| 61 |
+
parser.add_argument("--test", default=[], nargs="+", type=str, help="Test CoNLL-U files.")
|
| 62 |
+
parser.add_argument("--train", default=[], nargs="+", type=str, help="Train CoNLL-U files.")
|
| 63 |
+
parser.add_argument("--train_sampling_exponent", default=0.5, type=float, help="Train sampling exponent.")
|
| 64 |
+
parser.add_argument("--transformers", nargs="+", type=str, help="Transformers models to use.")
|
| 65 |
+
parser.add_argument("--treebank_ids", default=False, action="store_true", help="Include treebank IDs on input.")
|
| 66 |
+
parser.add_argument("--threads", default=4, type=int, help="Maximum number of threads to use.")
|
| 67 |
+
parser.add_argument("--verbose", default=2, type=int, help="Verbosity")
|
| 68 |
+
parser.add_argument("--wandb", default=False, action="store_true", help="Log in WandB.")
|
| 69 |
+
parser.add_argument("--word_masking", default=None, type=float, help="Word masking")
|
| 70 |
+
|
| 71 |
+
os.environ["PYTORCH_MPS_HIGH_WATERMARK_RATIO"] = "0.0"
|
| 72 |
+
|
| 73 |
+
class UDDataset:
|
| 74 |
+
FORMS, LEMMAS, UPOS, XPOS, FEATS, HEAD, DEPREL, DEPS, MISC, FACTORS = range(10)
|
| 75 |
+
FACTORS_MAP = {"FORMS": FORMS, "LEMMAS": LEMMAS, "UPOS": UPOS, "XPOS": XPOS, "FEATS": FEATS,
|
| 76 |
+
"HEAD": HEAD, "DEPREL": DEPREL, "DEPS": DEPS, "MISC": MISC}
|
| 77 |
+
RE_EXTRAS = re.compile(r"^#|^\d+-|^\d+\.")
|
| 78 |
+
|
| 79 |
+
class Factor:
|
| 80 |
+
def __init__(self, train_factor: Self = None):
|
| 81 |
+
self.words_map = train_factor.words_map if train_factor else {"<unk>": 0}
|
| 82 |
+
self.words = train_factor.words if train_factor else ["<unk>"]
|
| 83 |
+
self.word_ids = []
|
| 84 |
+
self.strings = []
|
| 85 |
+
|
| 86 |
+
def __init__(self, path: str, args: argparse.Namespace, treebank_id: int|None = None, train_dataset: Self = None, text: str|None = None):
|
| 87 |
+
self.path = path
|
| 88 |
+
|
| 89 |
+
# Create factors and other variables
|
| 90 |
+
self.factors = []
|
| 91 |
+
for f in range(self.FACTORS):
|
| 92 |
+
self.factors.append(self.Factor(train_dataset.factors[f] if train_dataset is not None else None))
|
| 93 |
+
self._extras = []
|
| 94 |
+
|
| 95 |
+
lemma_transforms = collections.Counter()
|
| 96 |
+
|
| 97 |
+
# Load the CoNLL-U file
|
| 98 |
+
with open(path, "r", encoding="utf-8") if text is None else io.StringIO(text) as file:
|
| 99 |
+
in_sentence = False
|
| 100 |
+
for line in file:
|
| 101 |
+
line = line.rstrip("\r\n")
|
| 102 |
+
|
| 103 |
+
if line:
|
| 104 |
+
if self.RE_EXTRAS.match(line):
|
| 105 |
+
if in_sentence:
|
| 106 |
+
while len(self._extras) < len(self.factors[0].strings): self._extras.append([])
|
| 107 |
+
while len(self._extras[-1]) <= len(self.factors[0].strings[-1]):
|
| 108 |
+
self._extras[-1].append("")
|
| 109 |
+
else:
|
| 110 |
+
while len(self._extras) <= len(self.factors[0].strings): self._extras.append([])
|
| 111 |
+
if not len(self._extras[-1]): self._extras[-1].append("")
|
| 112 |
+
self._extras[-1][-1] += ("\n" if self._extras[-1][-1] else "") + line
|
| 113 |
+
continue
|
| 114 |
+
|
| 115 |
+
columns = line.split("\t")[1:]
|
| 116 |
+
for f in range(self.FACTORS):
|
| 117 |
+
factor = self.factors[f]
|
| 118 |
+
if not in_sentence:
|
| 119 |
+
factor.word_ids.append([])
|
| 120 |
+
factor.strings.append([])
|
| 121 |
+
|
| 122 |
+
word = columns[f]
|
| 123 |
+
factor.strings[-1].append(word)
|
| 124 |
+
|
| 125 |
+
# Add word to word_ids
|
| 126 |
+
if f == self.FORMS:
|
| 127 |
+
# For formw, we do not remap strings into IDs because the tokenizer will create the subwords IDs for us.
|
| 128 |
+
factor.word_ids[-1].append(0)
|
| 129 |
+
elif f == self.HEAD:
|
| 130 |
+
factor.word_ids[-1].append(int(word) if word != "_" else -1)
|
| 131 |
+
elif f == self.LEMMAS:
|
| 132 |
+
factor.word_ids[-1].append(0)
|
| 133 |
+
lemma_transforms[(columns[self.FORMS], word)] += 1
|
| 134 |
+
else:
|
| 135 |
+
if f == self.DEPREL and args.deprel == "universal":
|
| 136 |
+
word = word.split(":")[0]
|
| 137 |
+
if word not in factor.words_map:
|
| 138 |
+
if train_dataset is not None:
|
| 139 |
+
word = "<unk>"
|
| 140 |
+
else:
|
| 141 |
+
factor.words_map[word] = len(factor.words)
|
| 142 |
+
factor.words.append(word)
|
| 143 |
+
factor.word_ids[-1].append(factor.words_map[word])
|
| 144 |
+
in_sentence = True
|
| 145 |
+
else:
|
| 146 |
+
in_sentence = False
|
| 147 |
+
for factor in self.factors:
|
| 148 |
+
if len(factor.word_ids): factor.word_ids[-1] = np.array(factor.word_ids[-1], np.int32)
|
| 149 |
+
|
| 150 |
+
# Also load the file for evaluation if it is not a training dataset
|
| 151 |
+
if train_dataset is not None:
|
| 152 |
+
file.seek(0, io.SEEK_SET)
|
| 153 |
+
self.conllu_for_eval = latinpipe_evalatin24_eval.load_conllu(file)
|
| 154 |
+
|
| 155 |
+
# Construct lemma rules
|
| 156 |
+
self.finalize_lemma_rules(lemma_transforms, create_rules=train_dataset is None)
|
| 157 |
+
|
| 158 |
+
# The dataset consists of a single treebank
|
| 159 |
+
self.treebank_ranges = [(0, len(self))]
|
| 160 |
+
self.treebank_ids = [treebank_id]
|
| 161 |
+
|
| 162 |
+
# Create an empty tokenize cache
|
| 163 |
+
self._tokenizer_cache = {}
|
| 164 |
+
|
| 165 |
+
def __len__(self):
|
| 166 |
+
return len(self.factors[0].strings)
|
| 167 |
+
|
| 168 |
+
def save_mappings(self, path: str) -> None:
|
| 169 |
+
mappings = UDDataset.__new__(UDDataset)
|
| 170 |
+
mappings.factors = []
|
| 171 |
+
for factor in self.factors:
|
| 172 |
+
mappings.factors.append(UDDataset.Factor.__new__(UDDataset.Factor))
|
| 173 |
+
mappings.factors[-1].words = factor.words
|
| 174 |
+
with open(path, "wb") as mappings_file:
|
| 175 |
+
pickle.dump(mappings, mappings_file, protocol=4)
|
| 176 |
+
|
| 177 |
+
@staticmethod
|
| 178 |
+
def from_mappings(path: str) -> Self:
|
| 179 |
+
with open(path, "rb") as mappings_file:
|
| 180 |
+
mappings = pickle.load(mappings_file)
|
| 181 |
+
for factor in mappings.factors:
|
| 182 |
+
factor.words_map = {word: i for i, word in enumerate(factor.words)}
|
| 183 |
+
return mappings
|
| 184 |
+
|
| 185 |
+
@staticmethod
|
| 186 |
+
def create_lemma_rule(form: str, lemma: str) -> str:
|
| 187 |
+
diff = difflib.SequenceMatcher(None, form.lower(), lemma.lower(), False)
|
| 188 |
+
rule, in_prefix = [], True
|
| 189 |
+
for tag, i1, i2, j1, j2 in diff.get_opcodes():
|
| 190 |
+
if i2 > len(form) // 3 and in_prefix:
|
| 191 |
+
in_prefix = False
|
| 192 |
+
if tag == "equal":
|
| 193 |
+
mode, jd = "L" if lemma[j2 - 1].islower() else "U", j2 - 1
|
| 194 |
+
while jd > j1 and lemma[jd - 1].islower() == lemma[j2 - 1].islower(): jd -= 1
|
| 195 |
+
rule.extend(["l" if lemma[j].islower() else "u" for j in range(j1, jd)])
|
| 196 |
+
rule.extend(mode * (len(form) - i2 + 1))
|
| 197 |
+
if tag in ["replace", "delete"]:
|
| 198 |
+
rule.extend("D" * (len(form) - i2 + 1))
|
| 199 |
+
if tag in ["replace", "insert"]:
|
| 200 |
+
rule.extend("i" + lemma[j] for j in range(j1, j2))
|
| 201 |
+
else:
|
| 202 |
+
if tag == "equal":
|
| 203 |
+
rule.extend(["l" if lemma[j].islower() else "u" for j in range(j1, j2)])
|
| 204 |
+
if tag in ["replace", "delete"]:
|
| 205 |
+
rule.extend("d" * (i2 - i1))
|
| 206 |
+
if tag in ["replace", "insert"]:
|
| 207 |
+
rule.extend("i" + lemma[j] for j in range(j1, j2))
|
| 208 |
+
return "".join(rule)
|
| 209 |
+
|
| 210 |
+
@staticmethod
|
| 211 |
+
def apply_lemma_rule(rule: str, form: str) -> str:
|
| 212 |
+
def error():
|
| 213 |
+
# print("Error: cannot decode lemma rule '{}' with form '{}', copying input.".format(rule, form))
|
| 214 |
+
return form
|
| 215 |
+
|
| 216 |
+
if rule == "<unk>":
|
| 217 |
+
return form
|
| 218 |
+
|
| 219 |
+
lemma, r, i = [], 0, 0
|
| 220 |
+
while r < len(rule):
|
| 221 |
+
if rule[r] == "i":
|
| 222 |
+
if r + 1 == len(rule):
|
| 223 |
+
return error()
|
| 224 |
+
r += 1
|
| 225 |
+
lemma.append(rule[r])
|
| 226 |
+
elif rule[r] == "d":
|
| 227 |
+
i += 1
|
| 228 |
+
elif rule[r] in ("l", "u"):
|
| 229 |
+
if i == len(form):
|
| 230 |
+
return error()
|
| 231 |
+
lemma.append(form[i].lower() if rule[r] == "l" else form[i].upper())
|
| 232 |
+
i += 1
|
| 233 |
+
elif rule[r] in ("L", "U", "D"):
|
| 234 |
+
i2 = len(form)
|
| 235 |
+
while r + 1 < len(rule) and rule[r + 1] == rule[r]:
|
| 236 |
+
r += 1
|
| 237 |
+
i2 -= 1
|
| 238 |
+
if i2 < i:
|
| 239 |
+
return error()
|
| 240 |
+
if rule[r] == "L":
|
| 241 |
+
lemma.extend(form[i:i2].lower())
|
| 242 |
+
if rule[r] == "U":
|
| 243 |
+
lemma.extend(form[i:i2].upper())
|
| 244 |
+
i = i2
|
| 245 |
+
else:
|
| 246 |
+
return error()
|
| 247 |
+
r += 1
|
| 248 |
+
if i != len(form) or not lemma:
|
| 249 |
+
return error()
|
| 250 |
+
return "".join(lemma)
|
| 251 |
+
|
| 252 |
+
def finalize_lemma_rules(self, lemma_transforms: collections.Counter, create_rules: bool) -> None:
|
| 253 |
+
forms, lemmas = self.factors[self.FORMS], self.factors[self.LEMMAS]
|
| 254 |
+
|
| 255 |
+
# Generate all rules
|
| 256 |
+
rules_merged, rules_all = collections.Counter(), {}
|
| 257 |
+
for form, lemma in lemma_transforms:
|
| 258 |
+
rule = self.create_lemma_rule(form, lemma)
|
| 259 |
+
rules_all[(form, lemma)] = rule
|
| 260 |
+
if create_rules:
|
| 261 |
+
rules_merged[rule] += 1
|
| 262 |
+
|
| 263 |
+
# Keep the rules that are used more than once
|
| 264 |
+
if create_rules:
|
| 265 |
+
for rule, count in rules_merged.items():
|
| 266 |
+
if count > 1:
|
| 267 |
+
lemmas.words_map[rule] = len(lemmas.words)
|
| 268 |
+
lemmas.words.append(rule)
|
| 269 |
+
|
| 270 |
+
# Store the rules in the dataset
|
| 271 |
+
for i in range(len(forms.strings)):
|
| 272 |
+
for j in range(len(forms.strings[i])):
|
| 273 |
+
rule = rules_all.get((forms.strings[i][j], lemmas.strings[i][j]))
|
| 274 |
+
lemmas.word_ids[i][j] = lemmas.words_map.get(rule, 0)
|
| 275 |
+
|
| 276 |
+
def tokenize(self, tokenizer: transformers.PreTrainedTokenizer) -> tuple[list[np.ndarray], list[np.ndarray]]:
|
| 277 |
+
if tokenizer not in self._tokenizer_cache:
|
| 278 |
+
assert tokenizer.cls_token_id is not None, "The tokenizer must have a CLS token"
|
| 279 |
+
|
| 280 |
+
tokenized = tokenizer(self.factors[0].strings, add_special_tokens=True, is_split_into_words=True)
|
| 281 |
+
|
| 282 |
+
tokens, word_indices = [], []
|
| 283 |
+
for i, sentence in enumerate(tokenized.input_ids):
|
| 284 |
+
offset = 0
|
| 285 |
+
if not len(sentence) or sentence[0] != tokenizer.cls_token_id:
|
| 286 |
+
# Handle tokenizers that do not add CLS tokens, which we need for prediction
|
| 287 |
+
# of the root nodes during parsing. For such tokenizers, we added the CLS token
|
| 288 |
+
# manually already, but the build_inputs_with_special_tokens() might not have added it.
|
| 289 |
+
sentence = [tokenizer.cls_token_id] + sentence
|
| 290 |
+
offset = 1
|
| 291 |
+
|
| 292 |
+
treebank_id = None
|
| 293 |
+
for id_, (start, end) in zip(self.treebank_ids, self.treebank_ranges):
|
| 294 |
+
if start <= i < end:
|
| 295 |
+
treebank_id = id_
|
| 296 |
+
if treebank_id is not None:
|
| 297 |
+
sentence.insert(1, tokenizer.additional_special_tokens_ids[treebank_id])
|
| 298 |
+
offset += 1
|
| 299 |
+
|
| 300 |
+
tokens.append(np.array(sentence, dtype=np.int32))
|
| 301 |
+
word_indices.append([(0, 0)])
|
| 302 |
+
for j in range(len(self.factors[0].strings[i])):
|
| 303 |
+
span = tokenized.word_to_tokens(i, j)
|
| 304 |
+
if (span == None):
|
| 305 |
+
print("-x-x-x-", i, j)
|
| 306 |
+
try:
|
| 307 |
+
word_indices[-1].append((offset + span.start, offset + span.end - 1))
|
| 308 |
+
except:
|
| 309 |
+
#abracadabra = 0
|
| 310 |
+
print(treebank_id)
|
| 311 |
+
input("??")
|
| 312 |
+
word_indices[-1] = np.array(word_indices[-1], dtype=np.int32)
|
| 313 |
+
|
| 314 |
+
|
| 315 |
+
self._tokenizer_cache[tokenizer] = (tokens, word_indices)
|
| 316 |
+
|
| 317 |
+
return self._tokenizer_cache[tokenizer]
|
| 318 |
+
|
| 319 |
+
def write_sentence(self, output: io.TextIOBase, index: int, overrides: list = None) -> None:
|
| 320 |
+
assert index < len(self.factors[0].strings), "Sentence index out of range"
|
| 321 |
+
|
| 322 |
+
for i in range(len(self.factors[0].strings[index]) + 1):
|
| 323 |
+
# Start by writing extras
|
| 324 |
+
if index < len(self._extras) and i < len(self._extras[index]) and self._extras[index][i]:
|
| 325 |
+
print(self._extras[index][i], file=output)
|
| 326 |
+
if i == len(self.factors[0].strings[index]): break
|
| 327 |
+
|
| 328 |
+
fields = []
|
| 329 |
+
fields.append(str(i + 1))
|
| 330 |
+
for f in range(self.FACTORS):
|
| 331 |
+
factor = self.factors[f]
|
| 332 |
+
field = factor.strings[index][i]
|
| 333 |
+
|
| 334 |
+
# Overrides
|
| 335 |
+
if overrides is not None and f < len(overrides) and overrides[f] is not None:
|
| 336 |
+
override = overrides[f][i]
|
| 337 |
+
if f == self.HEAD:
|
| 338 |
+
field = str(override) if override >= 0 else "_"
|
| 339 |
+
else:
|
| 340 |
+
field = factor.words[override]
|
| 341 |
+
if f == self.LEMMAS:
|
| 342 |
+
field = self.apply_lemma_rule(field, self.factors[self.FORMS].strings[index][i])
|
| 343 |
+
fields.append(field)
|
| 344 |
+
|
| 345 |
+
print("\t".join(fields), file=output)
|
| 346 |
+
print(file=output)
|
| 347 |
+
|
| 348 |
+
|
| 349 |
+
class UDDatasetMerged(UDDataset):
|
| 350 |
+
def __init__(self, datasets: list[UDDataset]):
|
| 351 |
+
# Create factors and other variables
|
| 352 |
+
self.factors = []
|
| 353 |
+
for f in range(self.FACTORS):
|
| 354 |
+
self.factors.append(self.Factor(None))
|
| 355 |
+
|
| 356 |
+
lemma_transforms = collections.Counter()
|
| 357 |
+
|
| 358 |
+
self.treebank_ranges, self.treebank_ids = [], []
|
| 359 |
+
for dataset in datasets:
|
| 360 |
+
assert len(dataset.treebank_ranges) == len(dataset.treebank_ids) == 1
|
| 361 |
+
self.treebank_ranges.append((len(self), len(self) + len(dataset)))
|
| 362 |
+
self.treebank_ids.append(dataset.treebank_ids[0])
|
| 363 |
+
for s in range(len(dataset)):
|
| 364 |
+
for f in range(self.FACTORS):
|
| 365 |
+
factor = self.factors[f]
|
| 366 |
+
factor.strings.append(dataset.factors[f].strings[s])
|
| 367 |
+
factor.word_ids.append([])
|
| 368 |
+
for i, word in enumerate(dataset.factors[f].strings[s]):
|
| 369 |
+
if f == self.FORMS:
|
| 370 |
+
# We do not remap strings into IDs because the tokenizer will create the subwords IDs for us.
|
| 371 |
+
factor.word_ids[-1].append(0)
|
| 372 |
+
if f == self.HEAD:
|
| 373 |
+
factor.word_ids[-1].append(word)
|
| 374 |
+
elif f == self.LEMMAS:
|
| 375 |
+
factor.word_ids[-1].append(0)
|
| 376 |
+
lemma_transforms[(dataset.factors[self.FORMS].strings[s][i], word)] += 1
|
| 377 |
+
else:
|
| 378 |
+
if word not in factor.words_map:
|
| 379 |
+
factor.words_map[word] = len(factor.words)
|
| 380 |
+
factor.words.append(word)
|
| 381 |
+
factor.word_ids[-1].append(factor.words_map[word])
|
| 382 |
+
self.factors[f].word_ids[-1] = np.array(self.factors[f].word_ids[-1], np.int32)
|
| 383 |
+
|
| 384 |
+
# Construct lemma rules
|
| 385 |
+
self.finalize_lemma_rules(lemma_transforms, create_rules=True)
|
| 386 |
+
|
| 387 |
+
# Create an empty tokenize cache
|
| 388 |
+
self._tokenizer_cache = {}
|
| 389 |
+
|
| 390 |
+
|
| 391 |
+
class TorchUDDataset(torch.utils.data.Dataset):
|
| 392 |
+
def __init__(self, ud_dataset: UDDataset, tokenizers: list[transformers.PreTrainedTokenizer], args: argparse.Namespace, training: bool):
|
| 393 |
+
self.ud_dataset = ud_dataset
|
| 394 |
+
self.training = training
|
| 395 |
+
self._outputs_to_input = [args.tags.index(tag) for tag in args.embed_tags]
|
| 396 |
+
|
| 397 |
+
self._inputs = [ud_dataset.tokenize(tokenizer) for tokenizer in tokenizers]
|
| 398 |
+
self._outputs = [ud_dataset.factors[tag].word_ids for tag in args.tags]
|
| 399 |
+
if args.parse:
|
| 400 |
+
self._outputs.append(ud_dataset.factors[ud_dataset.HEAD].word_ids)
|
| 401 |
+
self._outputs.append(ud_dataset.factors[ud_dataset.DEPREL].word_ids)
|
| 402 |
+
|
| 403 |
+
# Trim the sentences if needed
|
| 404 |
+
if training and args.max_train_sentence_len:
|
| 405 |
+
trimmed_sentences = 0
|
| 406 |
+
for index in range(len(self)): # Over sentences
|
| 407 |
+
max_words, need_trimming = None, False
|
| 408 |
+
for tokens, word_indices in self._inputs: # Over transformers
|
| 409 |
+
if max_words is None:
|
| 410 |
+
max_words = len(word_indices[index])
|
| 411 |
+
while word_indices[index][max_words - 1, 1] >= args.max_train_sentence_len:
|
| 412 |
+
max_words -= 1
|
| 413 |
+
need_trimming = True
|
| 414 |
+
assert max_words >= 2, "Sentence too short after trimming"
|
| 415 |
+
|
| 416 |
+
if need_trimming:
|
| 417 |
+
for tokens, word_indices in self._inputs: # Over transformers
|
| 418 |
+
tokens[index] = tokens[index][:word_indices[index][max_words - 1, 1] + 1]
|
| 419 |
+
word_indices[index] = word_indices[index][:max_words]
|
| 420 |
+
|
| 421 |
+
for output in self._outputs:
|
| 422 |
+
output[index] = output[index][:max_words - 1] # No CLS tokens in outputs
|
| 423 |
+
if args.parse:
|
| 424 |
+
self._outputs[-2][index] = np.array([head if head < max_words else -1 for head in self._outputs[-2][index]], np.int32)
|
| 425 |
+
|
| 426 |
+
trimmed_sentences += 1
|
| 427 |
+
if trimmed_sentences:
|
| 428 |
+
print("Trimmed {} out of {} sentences".format(trimmed_sentences, len(self)))
|
| 429 |
+
|
| 430 |
+
def __len__(self):
|
| 431 |
+
return len(self.ud_dataset)
|
| 432 |
+
|
| 433 |
+
def __getitem__(self, index: int):
|
| 434 |
+
inputs = []
|
| 435 |
+
for tokens, word_indices in self._inputs:
|
| 436 |
+
inputs.append(torch.from_numpy(tokens[index]))
|
| 437 |
+
inputs.append(torch.from_numpy(word_indices[index]))
|
| 438 |
+
for i in self._outputs_to_input:
|
| 439 |
+
inputs.append(torch.from_numpy(self._outputs[i][index]))
|
| 440 |
+
|
| 441 |
+
outputs = []
|
| 442 |
+
for output in self._outputs:
|
| 443 |
+
outputs.append(torch.from_numpy(output[index]))
|
| 444 |
+
|
| 445 |
+
return inputs, outputs
|
| 446 |
+
|
| 447 |
+
|
| 448 |
+
class TorchUDDataLoader(torch.utils.data.DataLoader):
|
| 449 |
+
class MergedDatasetSampler(torch.utils.data.Sampler):
|
| 450 |
+
def __init__(self, ud_dataset: UDDataset, args: argparse.Namespace):
|
| 451 |
+
self._treebank_ranges = ud_dataset.treebank_ranges
|
| 452 |
+
self._sentences_per_epoch = args.steps_per_epoch * args.batch_size
|
| 453 |
+
self._generator = torch.Generator().manual_seed(args.seed)
|
| 454 |
+
|
| 455 |
+
treebank_weights = np.array([r[1] - r[0] for r in self._treebank_ranges], np.float32)
|
| 456 |
+
treebank_weights = treebank_weights ** args.train_sampling_exponent
|
| 457 |
+
treebank_weights /= np.sum(treebank_weights)
|
| 458 |
+
self._treebank_sizes = np.array(treebank_weights * self._sentences_per_epoch, np.int32)
|
| 459 |
+
self._treebank_sizes[:self._sentences_per_epoch - np.sum(self._treebank_sizes)] += 1
|
| 460 |
+
self._treebank_indices = [[] for _ in self._treebank_ranges]
|
| 461 |
+
|
| 462 |
+
def __len__(self):
|
| 463 |
+
return self._sentences_per_epoch
|
| 464 |
+
|
| 465 |
+
def __iter__(self):
|
| 466 |
+
indices = []
|
| 467 |
+
for i in range(len(self._treebank_ranges)):
|
| 468 |
+
required = self._treebank_sizes[i]
|
| 469 |
+
while required:
|
| 470 |
+
if not len(self._treebank_indices[i]):
|
| 471 |
+
self._treebank_indices[i] = self._treebank_ranges[i][0] + torch.randperm(
|
| 472 |
+
self._treebank_ranges[i][1] - self._treebank_ranges[i][0], generator=self._generator)
|
| 473 |
+
indices.append(self._treebank_indices[i][:required])
|
| 474 |
+
required -= min(len(self._treebank_indices[i]), required)
|
| 475 |
+
indices = torch.concatenate(indices, axis=0)
|
| 476 |
+
return iter(indices[torch.randperm(len(indices), generator=self._generator)])
|
| 477 |
+
|
| 478 |
+
def _collate_fn(self, batch):
|
| 479 |
+
inputs, outputs = zip(*batch)
|
| 480 |
+
|
| 481 |
+
batch_inputs = []
|
| 482 |
+
for sequences in zip(*inputs):
|
| 483 |
+
batch_inputs.append(torch.nn.utils.rnn.pad_sequence(sequences, batch_first=True, padding_value=-1))
|
| 484 |
+
|
| 485 |
+
batch_outputs = []
|
| 486 |
+
for output in zip(*outputs):
|
| 487 |
+
batch_outputs.append(torch.nn.utils.rnn.pad_sequence(output, batch_first=True, padding_value=-1))
|
| 488 |
+
|
| 489 |
+
batch_weights = [batch_output != -1 for batch_output in batch_outputs]
|
| 490 |
+
|
| 491 |
+
return tuple(batch_inputs), tuple(batch_outputs), tuple(batch_weights)
|
| 492 |
+
|
| 493 |
+
def __init__(self, dataset: TorchUDDataset, args: argparse.Namespace, **kwargs):
|
| 494 |
+
sampler = None
|
| 495 |
+
if dataset.training:
|
| 496 |
+
if len(dataset.ud_dataset.treebank_ranges) == 1:
|
| 497 |
+
sampler = torch.utils.data.RandomSampler(dataset, generator=torch.Generator().manual_seed(args.seed))
|
| 498 |
+
else:
|
| 499 |
+
assert args.steps_per_epoch is not None, "Steps per epoch must be specified when training on multiple treebanks"
|
| 500 |
+
sampler = self.MergedDatasetSampler(dataset.ud_dataset, args)
|
| 501 |
+
super().__init__(dataset, batch_size=args.batch_size, sampler=sampler, collate_fn=self._collate_fn, **kwargs)
|
| 502 |
+
|
| 503 |
+
|
| 504 |
+
class LatinPipeModel(keras.Model):
|
| 505 |
+
class HFTransformerLayer(keras.layers.Layer):
|
| 506 |
+
def __init__(self, transformer: transformers.PreTrainedModel, subword_combination: str, word_masking: float = None, mask_token_id: int = None, **kwargs):
|
| 507 |
+
super().__init__(**kwargs)
|
| 508 |
+
self._transformer = transformer
|
| 509 |
+
self._subword_combination = subword_combination
|
| 510 |
+
self._word_masking = word_masking
|
| 511 |
+
self._mask_token_id = mask_token_id
|
| 512 |
+
|
| 513 |
+
def call(self, inputs, word_indices, training=None):
|
| 514 |
+
if training and self._word_masking:
|
| 515 |
+
mask = keras.ops.cast(keras.random.uniform(keras.ops.shape(inputs), dtype="float32") < self._word_masking, inputs.dtype)
|
| 516 |
+
inputs = (1 - mask) * inputs + mask * self._mask_token_id
|
| 517 |
+
if (training or False) != self._transformer.training:
|
| 518 |
+
self._transformer.train(training or False)
|
| 519 |
+
if self._subword_combination != "last":
|
| 520 |
+
first_subwords = keras.ops.take_along_axis(
|
| 521 |
+
self._transformer(keras.ops.maximum(inputs, 0), attention_mask=inputs > -1).last_hidden_state,
|
| 522 |
+
keras.ops.expand_dims(keras.ops.maximum(word_indices[..., 0], 0), axis=-1),
|
| 523 |
+
axis=1,
|
| 524 |
+
)
|
| 525 |
+
if self._subword_combination != "first":
|
| 526 |
+
last_subwords = keras.ops.take_along_axis(
|
| 527 |
+
self._transformer(keras.ops.maximum(inputs, 0), attention_mask=inputs > -1).last_hidden_state,
|
| 528 |
+
keras.ops.expand_dims(keras.ops.maximum(word_indices[..., 1], 0), axis=-1),
|
| 529 |
+
axis=1,
|
| 530 |
+
)
|
| 531 |
+
if self._subword_combination == "first":
|
| 532 |
+
return first_subwords
|
| 533 |
+
elif self._subword_combination == "last":
|
| 534 |
+
return last_subwords
|
| 535 |
+
elif self._subword_combination == "sum":
|
| 536 |
+
return first_subwords + last_subwords
|
| 537 |
+
elif self._subword_combination == "concat":
|
| 538 |
+
return keras.ops.concatenate([first_subwords, last_subwords], axis=-1)
|
| 539 |
+
else:
|
| 540 |
+
raise ValueError("Unknown subword combination '{}'".format(self._subword_combination))
|
| 541 |
+
|
| 542 |
+
class LSTMTorch(keras.layers.Layer):
|
| 543 |
+
def __init__(self, units: int, **kwargs):
|
| 544 |
+
super().__init__(**kwargs)
|
| 545 |
+
self._units = units
|
| 546 |
+
|
| 547 |
+
def build(self, input_shape):
|
| 548 |
+
self._lstm = torch.nn.LSTM(input_shape[-1], self._units, batch_first=True, bidirectional=True)
|
| 549 |
+
|
| 550 |
+
def call(self, inputs, lengths):
|
| 551 |
+
packed_result, _ = self._lstm.module(torch.nn.utils.rnn.pack_padded_sequence(inputs, lengths.cpu(), batch_first=True, enforce_sorted=False))
|
| 552 |
+
unpacked_result = torch.nn.utils.rnn.unpack_sequence(packed_result)
|
| 553 |
+
return torch.nn.utils.rnn.pad_sequence(unpacked_result, batch_first=True, padding_value=0)
|
| 554 |
+
|
| 555 |
+
class GRUTorch(keras.layers.Layer):
|
| 556 |
+
def __init__(self, units: int, **kwargs):
|
| 557 |
+
super().__init__(**kwargs)
|
| 558 |
+
self._units = units
|
| 559 |
+
|
| 560 |
+
def build(self, input_shape):
|
| 561 |
+
self._gru = torch.nn.GRU(input_shape[-1], self._units, batch_first=True, bidirectional=True)
|
| 562 |
+
|
| 563 |
+
def call(self, inputs, lengths):
|
| 564 |
+
packed_result, _ = self._gru(torch.nn.utils.rnn.pack_padded_sequence(inputs, lengths.cpu(), batch_first=True, enforce_sorted=False))
|
| 565 |
+
unpacked_result = torch.nn.utils.rnn.unpack_sequence(packed_result)
|
| 566 |
+
return torch.nn.utils.rnn.pad_sequence(unpacked_result, batch_first=True, padding_value=0)
|
| 567 |
+
|
| 568 |
+
class ParsingHead(keras.layers.Layer):
|
| 569 |
+
def __init__(self, num_deprels: int, task_hidden_layer: int, parse_attention_dim: int, dropout: float, **kwargs):
|
| 570 |
+
super().__init__(**kwargs)
|
| 571 |
+
self._head_queries_hidden = keras.layers.Dense(task_hidden_layer, activation="relu")
|
| 572 |
+
self._head_queries_output = keras.layers.Dense(parse_attention_dim)
|
| 573 |
+
self._head_keys_hidden = keras.layers.Dense(task_hidden_layer, activation="relu")
|
| 574 |
+
self._head_keys_output = keras.layers.Dense(parse_attention_dim)
|
| 575 |
+
self._deprel_hidden = keras.layers.Dense(task_hidden_layer, activation="relu")
|
| 576 |
+
self._deprel_output = keras.layers.Dense(num_deprels)
|
| 577 |
+
self._dropout = keras.layers.Dropout(dropout)
|
| 578 |
+
|
| 579 |
+
def call(self, embeddings, embeddings_wo_root, embeddings_mask):
|
| 580 |
+
head_queries = self._head_queries_output(self._dropout(self._head_queries_hidden(embeddings_wo_root)))
|
| 581 |
+
head_keys = self._head_keys_output(self._dropout(self._head_keys_hidden(embeddings)))
|
| 582 |
+
head_scores = keras.ops.matmul(head_queries, keras.ops.transpose(head_keys, axes=[0, 2, 1])) / keras.ops.sqrt(head_queries.shape[-1])
|
| 583 |
+
|
| 584 |
+
head_scores_mask = keras.ops.cast(keras.ops.expand_dims(embeddings_mask, axis=1), head_scores.dtype)
|
| 585 |
+
head_scores = head_scores * head_scores_mask - 1e9 * (1 - head_scores_mask)
|
| 586 |
+
|
| 587 |
+
predicted_heads = keras.ops.argmax(head_scores, axis=-1)
|
| 588 |
+
predicted_head_embeddings = keras.ops.take_along_axis(embeddings, keras.ops.expand_dims(predicted_heads, axis=-1), axis=1)
|
| 589 |
+
deprel_hidden = keras.ops.concatenate([embeddings_wo_root, predicted_head_embeddings], axis=-1)
|
| 590 |
+
deprel_scores = self._deprel_output(self._dropout(self._deprel_hidden(deprel_hidden)))
|
| 591 |
+
|
| 592 |
+
return head_scores, deprel_scores
|
| 593 |
+
|
| 594 |
+
class SparseCategoricalCrossentropyWithLabelSmoothing(keras.losses.Loss):
|
| 595 |
+
def __init__(self, from_logits: bool, label_smoothing: float, **kwargs):
|
| 596 |
+
super().__init__(**kwargs)
|
| 597 |
+
self._from_logits = from_logits
|
| 598 |
+
self._label_smoothing = label_smoothing
|
| 599 |
+
|
| 600 |
+
def call(self, y_true, y_pred):
|
| 601 |
+
y_gold = keras.ops.one_hot(keras.ops.maximum(y_true, 0), y_pred.shape[-1])
|
| 602 |
+
if self._label_smoothing:
|
| 603 |
+
y_pred_mask = keras.ops.cast(y_pred > -1e9, y_pred.dtype)
|
| 604 |
+
y_gold = y_gold * (1 - self._label_smoothing) + y_pred_mask / keras.ops.sum(y_pred_mask, axis=-1, keepdims=True) * self._label_smoothing
|
| 605 |
+
return keras.losses.categorical_crossentropy(y_gold, y_pred, from_logits=self._from_logits)
|
| 606 |
+
|
| 607 |
+
def __init__(self, dataset: UDDataset, args: argparse.Namespace):
|
| 608 |
+
self._dataset = dataset
|
| 609 |
+
self._args = args
|
| 610 |
+
|
| 611 |
+
# Create the transformer models
|
| 612 |
+
self._tokenizers, self._transformers = [], []
|
| 613 |
+
for name in args.transformers:
|
| 614 |
+
self._tokenizers.append(transformers.AutoTokenizer.from_pretrained(name, add_prefix_space=True))
|
| 615 |
+
|
| 616 |
+
transformer, transformer_opts = transformers.AutoModel, {}
|
| 617 |
+
if "mt5" in name.lower():
|
| 618 |
+
transformer = transformers.MT5EncoderModel
|
| 619 |
+
if name.endswith(("LaTa", "PhilTa")):
|
| 620 |
+
transformer = transformers.T5EncoderModel
|
| 621 |
+
if name.endswith(("LaBerta", "PhilBerta")):
|
| 622 |
+
transformer_opts["add_pooling_layer"] = False
|
| 623 |
+
|
| 624 |
+
if args.load:
|
| 625 |
+
transformer = transformer.from_config(transformers.AutoConfig.from_pretrained(name), **transformer_opts)
|
| 626 |
+
else:
|
| 627 |
+
transformer = transformer.from_pretrained(name, **transformer_opts)
|
| 628 |
+
|
| 629 |
+
# Create additional tokens
|
| 630 |
+
additional_tokens = {}
|
| 631 |
+
if args.treebank_ids:
|
| 632 |
+
additional_tokens["additional_special_tokens"] = ["[TREEBANK_ID_{}]".format(i) for i in range(len(dataset.treebank_ids))]
|
| 633 |
+
if self._tokenizers[-1].cls_token_id is None: # Generate CLS token if not present (for representing sentence root in parsing).
|
| 634 |
+
additional_tokens["cls_token"] = "[CLS]"
|
| 635 |
+
if additional_tokens:
|
| 636 |
+
self._tokenizers[-1].add_special_tokens(additional_tokens)
|
| 637 |
+
transformer.resize_token_embeddings(len(self._tokenizers[-1]))
|
| 638 |
+
if args.treebank_ids:
|
| 639 |
+
assert len(self._tokenizers[-1].additional_special_tokens) == len(dataset.treebank_ids)
|
| 640 |
+
|
| 641 |
+
self._transformers.append(self.HFTransformerLayer(transformer, args.subword_combination, args.word_masking, self._tokenizers[-1].mask_token_id))
|
| 642 |
+
|
| 643 |
+
# Create the network
|
| 644 |
+
inputs = []
|
| 645 |
+
for _ in args.transformers:
|
| 646 |
+
inputs.extend([keras.layers.Input(shape=[None], dtype="int32"), keras.layers.Input(shape=[None, 2], dtype="int32")])
|
| 647 |
+
for _ in args.embed_tags:
|
| 648 |
+
inputs.append(keras.layers.Input(shape=[None], dtype="int32"))
|
| 649 |
+
|
| 650 |
+
# Run the transformer models
|
| 651 |
+
embeddings = []
|
| 652 |
+
for tokens, word_indices, transformer in zip(inputs[::2], inputs[1::2], self._transformers):
|
| 653 |
+
embeddings.append(transformer(tokens, word_indices))
|
| 654 |
+
embeddings = keras.layers.Concatenate(axis=-1)(embeddings)
|
| 655 |
+
embeddings = keras.layers.Dropout(args.dropout)(embeddings)
|
| 656 |
+
|
| 657 |
+
# Heads for the tagging tasks
|
| 658 |
+
outputs = []
|
| 659 |
+
for tag in args.tags:
|
| 660 |
+
hidden = keras.layers.Dense(args.task_hidden_layer, activation="relu")(embeddings[:, 1:])
|
| 661 |
+
hidden = keras.layers.Dropout(args.dropout)(hidden)
|
| 662 |
+
outputs.append(keras.layers.Dense(len(dataset.factors[tag].words))(hidden))
|
| 663 |
+
|
| 664 |
+
# Head for parsing
|
| 665 |
+
if args.parse:
|
| 666 |
+
if args.embed_tags:
|
| 667 |
+
all_embeddings = [embeddings]
|
| 668 |
+
for factor, input_tags in zip(args.embed_tags, inputs[-len(args.embed_tags):]):
|
| 669 |
+
embedding_layer = keras.layers.Embedding(len(dataset.factors[factor].words) + 1, 256)
|
| 670 |
+
all_embeddings.append(keras.layers.Dropout(args.dropout)(embedding_layer(keras.ops.pad(input_tags + 1, [(0, 0), (1, 0)]))))
|
| 671 |
+
embeddings = keras.ops.concatenate(all_embeddings, axis=-1)
|
| 672 |
+
|
| 673 |
+
for i in range(args.rnn_layers):
|
| 674 |
+
if args.rnn_type in ["LSTM", "GRU"]:
|
| 675 |
+
hidden = keras.layers.Bidirectional(getattr(keras.layers, args.rnn_type)(args.rnn_dim, return_sequences=True))(embeddings, mask=inputs[1][..., 0] > -1)
|
| 676 |
+
elif args.rnn_type in ["LSTMTorch", "GRUTorch"]:
|
| 677 |
+
hidden = getattr(self, args.rnn_type)(args.rnn_dim)(embeddings, keras.ops.sum(inputs[1][..., 0] > -1, axis=-1))
|
| 678 |
+
hidden = keras.layers.Dropout(args.dropout)(hidden)
|
| 679 |
+
embeddings = hidden + (embeddings if i else 0)
|
| 680 |
+
|
| 681 |
+
outputs.extend(self.ParsingHead(
|
| 682 |
+
len(dataset.factors[dataset.DEPREL].words), args.task_hidden_layer, args.parse_attention_dim, args.dropout,
|
| 683 |
+
)(embeddings, embeddings[:, 1:], inputs[1][..., 0] > -1))
|
| 684 |
+
|
| 685 |
+
super().__init__(inputs=inputs, outputs=outputs)
|
| 686 |
+
if args.load:
|
| 687 |
+
self.load_weights(args.load[0])
|
| 688 |
+
|
| 689 |
+
def compile(self, epoch_batches: int, frozen: bool):
|
| 690 |
+
args = self._args
|
| 691 |
+
|
| 692 |
+
for transformer in self._transformers:
|
| 693 |
+
transformer.trainable = not frozen
|
| 694 |
+
|
| 695 |
+
if frozen:
|
| 696 |
+
schedule = 1e-3
|
| 697 |
+
else:
|
| 698 |
+
schedule = keras.optimizers.schedules.CosineDecay(
|
| 699 |
+
0. if args.learning_rate_warmup else args.learning_rate,
|
| 700 |
+
args.epochs * epoch_batches - args.learning_rate_warmup,
|
| 701 |
+
alpha=0.0 if args.learning_rate_decay != "none" else 1.0,
|
| 702 |
+
warmup_target=args.learning_rate if args.learning_rate_warmup else None,
|
| 703 |
+
warmup_steps=args.learning_rate_warmup,
|
| 704 |
+
)
|
| 705 |
+
if args.optimizer == "adam":
|
| 706 |
+
optimizer = keras.optimizers.Adam(schedule)
|
| 707 |
+
elif args.optimizer == "adafactor":
|
| 708 |
+
optimizer = keras.optimizers.Adafactor(schedule)
|
| 709 |
+
else:
|
| 710 |
+
raise ValueError("Unknown optimizer '{}'".format(args.optimizer))
|
| 711 |
+
super().compile(
|
| 712 |
+
optimizer=optimizer,
|
| 713 |
+
loss=self.SparseCategoricalCrossentropyWithLabelSmoothing(from_logits=True, label_smoothing=args.label_smoothing),
|
| 714 |
+
)
|
| 715 |
+
|
| 716 |
+
@property
|
| 717 |
+
def tokenizers(self) -> list[transformers.PreTrainedTokenizer]:
|
| 718 |
+
return self._tokenizers
|
| 719 |
+
|
| 720 |
+
def predict(self, dataloader: TorchUDDataLoader, save_as: str|None = None, args_override: argparse.Namespace|None = None) -> str:
|
| 721 |
+
ud_dataset = dataloader.dataset.ud_dataset
|
| 722 |
+
args = self._args if args_override is None else args_override
|
| 723 |
+
conllu, sentence = io.StringIO(), 0
|
| 724 |
+
|
| 725 |
+
for batch_inputs, _, _ in dataloader:
|
| 726 |
+
predictions = self.predict_on_batch(batch_inputs)
|
| 727 |
+
for b in range(len(batch_inputs[0])):
|
| 728 |
+
sentence_len = len(ud_dataset.factors[ud_dataset.FORMS].strings[sentence])
|
| 729 |
+
overrides = [None] * ud_dataset.FACTORS
|
| 730 |
+
for tag, prediction in zip(args.tags, predictions):
|
| 731 |
+
overrides[tag] = np.argmax(prediction[b, :sentence_len], axis=-1)
|
| 732 |
+
if args.parse:
|
| 733 |
+
heads, deprels = predictions[-2:]
|
| 734 |
+
padded_heads = np.zeros([sentence_len + 1, sentence_len + 1], dtype=np.float64)
|
| 735 |
+
padded_heads[1:] = heads[b, :sentence_len, :sentence_len + 1]
|
| 736 |
+
padded_heads[1:] -= np.max(padded_heads[1:], axis=-1, keepdims=True)
|
| 737 |
+
padded_heads[1:] -= np.log(np.sum(np.exp(padded_heads[1:]), axis=-1, keepdims=True))
|
| 738 |
+
if args.single_root:
|
| 739 |
+
selected_root = 1 + np.argmax(padded_heads[1:, 0])
|
| 740 |
+
padded_heads[:, 0] = np.nan
|
| 741 |
+
padded_heads[selected_root, 0] = 0
|
| 742 |
+
chosen_heads, _ = ufal.chu_liu_edmonds.chu_liu_edmonds(padded_heads)
|
| 743 |
+
overrides[ud_dataset.HEAD] = chosen_heads[1:]
|
| 744 |
+
overrides[ud_dataset.DEPREL] = np.argmax(deprels[b, :sentence_len], axis=-1)
|
| 745 |
+
ud_dataset.write_sentence(conllu, sentence, overrides)
|
| 746 |
+
sentence += 1
|
| 747 |
+
|
| 748 |
+
conllu = conllu.getvalue()
|
| 749 |
+
if save_as is not None:
|
| 750 |
+
os.makedirs(os.path.dirname(save_as), exist_ok=True)
|
| 751 |
+
with open(save_as, "w", encoding="utf-8") as conllu_file:
|
| 752 |
+
conllu_file.write(conllu)
|
| 753 |
+
return conllu
|
| 754 |
+
|
| 755 |
+
def evaluate(self, dataloader: TorchUDDataLoader, save_as: str|None = None, args_override: argparse.Namespace|None = None) -> tuple[str, dict[str, float]]:
|
| 756 |
+
conllu = self.predict(dataloader, save_as=save_as, args_override=args_override)
|
| 757 |
+
evaluation = latinpipe_evalatin24_eval.evaluate(dataloader.dataset.ud_dataset.conllu_for_eval, latinpipe_evalatin24_eval.load_conllu(io.StringIO(conllu)))
|
| 758 |
+
if save_as is not None:
|
| 759 |
+
os.makedirs(os.path.dirname(save_as), exist_ok=True)
|
| 760 |
+
with open(save_as + ".eval", "w", encoding="utf-8") as eval_file:
|
| 761 |
+
for metric, score in evaluation.items():
|
| 762 |
+
print("{}: {:.2f}%".format(metric, 100 * score.f1), file=eval_file)
|
| 763 |
+
return conllu, evaluation
|
| 764 |
+
|
| 765 |
+
|
| 766 |
+
class LatinPipeModelEnsemble:
|
| 767 |
+
def __init__(self, latinpipe_model: LatinPipeModel, args: argparse.Namespace):
|
| 768 |
+
self._latinpipe_model = latinpipe_model
|
| 769 |
+
self._args = args
|
| 770 |
+
|
| 771 |
+
def predict(self, dataloader: TorchUDDataLoader, save_as: str|None = None) -> str:
|
| 772 |
+
def log_softmax(logits):
|
| 773 |
+
logits -= np.max(logits, axis=-1, keepdims=True)
|
| 774 |
+
logits -= np.log(np.sum(np.exp(logits), axis=-1, keepdims=True))
|
| 775 |
+
return logits
|
| 776 |
+
ud_dataset = dataloader.dataset.ud_dataset
|
| 777 |
+
|
| 778 |
+
# First compute all predictions
|
| 779 |
+
overrides = [[0] * len(ud_dataset) if tag in self._args.tags + ([ud_dataset.HEAD, ud_dataset.DEPREL] if self._args.parse else []) else None
|
| 780 |
+
for tag in range(ud_dataset.FACTORS)]
|
| 781 |
+
for path in self._args.load:
|
| 782 |
+
self._latinpipe_model.load_weights(path)
|
| 783 |
+
sentence = 0
|
| 784 |
+
for batch_inputs, _, _ in dataloader:
|
| 785 |
+
predictions = self._latinpipe_model.predict_on_batch(batch_inputs)
|
| 786 |
+
for b in range(len(batch_inputs[0])):
|
| 787 |
+
sentence_len = len(ud_dataset.factors[ud_dataset.FORMS].strings[sentence])
|
| 788 |
+
for tag, prediction in zip(self._args.tags, predictions):
|
| 789 |
+
overrides[tag][sentence] += log_softmax(prediction[b, :sentence_len])
|
| 790 |
+
if self._args.parse:
|
| 791 |
+
overrides[ud_dataset.HEAD][sentence] += log_softmax(predictions[-2][b, :sentence_len, :sentence_len + 1])
|
| 792 |
+
overrides[ud_dataset.DEPREL][sentence] += log_softmax(predictions[-1][b, :sentence_len])
|
| 793 |
+
sentence += 1
|
| 794 |
+
|
| 795 |
+
# Predict the most likely class and generate CoNLL-U output
|
| 796 |
+
conllu = io.StringIO()
|
| 797 |
+
for sentence in range(len(ud_dataset)):
|
| 798 |
+
sentence_overrides = [None] * ud_dataset.FACTORS
|
| 799 |
+
for tag in self._args.tags:
|
| 800 |
+
sentence_overrides[tag] = np.argmax(overrides[tag][sentence], axis=-1)
|
| 801 |
+
if self._args.parse:
|
| 802 |
+
padded_heads = np.pad(overrides[ud_dataset.HEAD][sentence], [(1, 0), (0, 0)]).astype(np.float64)
|
| 803 |
+
if self._args.single_root:
|
| 804 |
+
selected_root = 1 + np.argmax(padded_heads[1:, 0])
|
| 805 |
+
padded_heads[:, 0] = np.nan
|
| 806 |
+
padded_heads[selected_root, 0] = 0
|
| 807 |
+
chosen_heads, _ = ufal.chu_liu_edmonds.chu_liu_edmonds(padded_heads)
|
| 808 |
+
sentence_overrides[ud_dataset.HEAD] = chosen_heads[1:]
|
| 809 |
+
sentence_overrides[ud_dataset.DEPREL] = np.argmax(overrides[ud_dataset.DEPREL][sentence], axis=-1)
|
| 810 |
+
ud_dataset.write_sentence(conllu, sentence, sentence_overrides)
|
| 811 |
+
|
| 812 |
+
conllu = conllu.getvalue()
|
| 813 |
+
if save_as is not None:
|
| 814 |
+
os.makedirs(os.path.dirname(save_as), exist_ok=True)
|
| 815 |
+
with open(save_as, "w", encoding="utf-8") as conllu_file:
|
| 816 |
+
conllu_file.write(conllu)
|
| 817 |
+
return conllu
|
| 818 |
+
|
| 819 |
+
def evaluate(self, dataloader: TorchUDDataLoader, save_as: str|None = None) -> tuple[str, dict[str, float]]:
|
| 820 |
+
return LatinPipeModel.evaluate(self, dataloader, save_as=save_as)
|
| 821 |
+
|
| 822 |
+
|
| 823 |
+
def main(params: list[str] | None = None) -> None:
|
| 824 |
+
args = parser.parse_args(params)
|
| 825 |
+
|
| 826 |
+
# If supplied, load configuration from a trained model
|
| 827 |
+
if args.load:
|
| 828 |
+
with open(os.path.join(os.path.dirname(args.load[0]), "options.json"), mode="r") as options_file:
|
| 829 |
+
args = argparse.Namespace(**{k: v for k, v in json.load(options_file).items() if k not in [
|
| 830 |
+
"dev", "exp", "load", "test", "threads", "verbose"]})
|
| 831 |
+
args = parser.parse_args(params, namespace=args)
|
| 832 |
+
else:
|
| 833 |
+
assert args.train, "Either --load or --train must be set."
|
| 834 |
+
assert args.transformers, "At least one transformer must be specified."
|
| 835 |
+
|
| 836 |
+
# Post-process arguments
|
| 837 |
+
args.embed_tags = [UDDataset.FACTORS_MAP[tag] for tag in args.embed_tags.split(",") if tag]
|
| 838 |
+
args.tags = [UDDataset.FACTORS_MAP[tag] for tag in args.tags.split(",") if tag]
|
| 839 |
+
args.script = os.path.basename(__file__)
|
| 840 |
+
|
| 841 |
+
# Create logdir
|
| 842 |
+
args.logdir = os.path.join("logs", "{}{}-{}-{}-s{}".format(
|
| 843 |
+
args.exp + "-" if args.exp else "",
|
| 844 |
+
os.path.splitext(os.path.basename(globals().get("__file__", "notebook")))[0],
|
| 845 |
+
os.environ.get("SLURM_JOB_ID", ""),
|
| 846 |
+
datetime.datetime.now().strftime("%y%m%d_%H%M%S"),
|
| 847 |
+
args.seed,
|
| 848 |
+
# ",".join(("{}={}".format(
|
| 849 |
+
# re.sub("(.)[^_]*_?", r"\1", k),
|
| 850 |
+
# ",".join(re.sub(r"^.*/", "", str(x)) for x in ((v if len(v) <= 1 else [v[0], "..."]) if isinstance(v, list) else [v])),
|
| 851 |
+
# ) for k, v in sorted(vars(args).items()) if k not in ["dev", "exp", "load", "test", "threads", "verbose"]))
|
| 852 |
+
))
|
| 853 |
+
print(json.dumps(vars(args), sort_keys=True, ensure_ascii=False, indent=2))
|
| 854 |
+
os.makedirs(args.logdir, exist_ok=True)
|
| 855 |
+
with open(os.path.join(args.logdir, "options.json"), mode="w") as options_file:
|
| 856 |
+
json.dump(vars(args), options_file, sort_keys=True, ensure_ascii=False, indent=2)
|
| 857 |
+
|
| 858 |
+
# Set the random seed and the number of threads
|
| 859 |
+
keras.utils.set_random_seed(args.seed)
|
| 860 |
+
torch.set_num_threads(args.threads)
|
| 861 |
+
torch.set_num_interop_threads(args.threads)
|
| 862 |
+
|
| 863 |
+
# Load the data
|
| 864 |
+
if args.treebank_ids and max(len(args.train), len(args.dev), len(args.test)) > 1:
|
| 865 |
+
print("WARNING: With treebank_ids, treebanks must always be in the same position in the train/dev/test.")
|
| 866 |
+
if args.load:
|
| 867 |
+
train = UDDataset.from_mappings(os.path.join(os.path.dirname(args.load[0]), "mappings.pkl"))
|
| 868 |
+
else:
|
| 869 |
+
train = UDDatasetMerged([UDDataset(path, args, treebank_id=i if args.treebank_ids else None) for i, path in enumerate(args.train)])
|
| 870 |
+
train.save_mappings(os.path.join(args.logdir, "mappings.pkl"))
|
| 871 |
+
devs = [UDDataset(path, args, treebank_id=i if args.treebank_ids else None, train_dataset=train) for i, path in enumerate(args.dev)]
|
| 872 |
+
tests = [UDDataset(path, args, treebank_id=i if args.treebank_ids else None, train_dataset=train) for i, path in enumerate(args.test)]
|
| 873 |
+
|
| 874 |
+
# Create the model
|
| 875 |
+
model = LatinPipeModel(train, args)
|
| 876 |
+
|
| 877 |
+
# Create the dataloaders
|
| 878 |
+
if not args.load:
|
| 879 |
+
train_dataloader = TorchUDDataLoader(TorchUDDataset(train, model.tokenizers, args, training=True), args)
|
| 880 |
+
dev_dataloaders = [TorchUDDataLoader(TorchUDDataset(dataset, model.tokenizers, args, training=False), args) for dataset in devs]
|
| 881 |
+
test_dataloaders = [TorchUDDataLoader(TorchUDDataset(dataset, model.tokenizers, args, training=False), args) for dataset in tests]
|
| 882 |
+
|
| 883 |
+
# Perform prediction if requested
|
| 884 |
+
if args.load:
|
| 885 |
+
if len(args.load) > 1:
|
| 886 |
+
model = LatinPipeModelEnsemble(model, args)
|
| 887 |
+
for dataloader in dev_dataloaders:
|
| 888 |
+
model.evaluate(dataloader, save_as=os.path.splitext(
|
| 889 |
+
os.path.join(args.exp, os.path.basename(dataloader.dataset.ud_dataset.path)) if args.exp else dataloader.dataset.ud_dataset.path
|
| 890 |
+
)[0] + ".predicted.conllu")
|
| 891 |
+
for dataloader in test_dataloaders:
|
| 892 |
+
model.predict(dataloader, save_as=os.path.splitext(
|
| 893 |
+
os.path.join(args.exp, os.path.basename(dataloader.dataset.ud_dataset.path)) if args.exp else dataloader.dataset.ud_dataset.path
|
| 894 |
+
)[0] + ".predicted.conllu")
|
| 895 |
+
return
|
| 896 |
+
|
| 897 |
+
# Train the model
|
| 898 |
+
class Evaluator(keras.callbacks.Callback):
|
| 899 |
+
def __init__(self, wandb_log):
|
| 900 |
+
super().__init__()
|
| 901 |
+
self._wandb_log = wandb_log
|
| 902 |
+
self._metrics = [["", "Lemmas", "UPOS", "XPOS", "UFeats"][tag] for tag in args.tags] + (["UAS", "LAS"] if args.parse else [])
|
| 903 |
+
|
| 904 |
+
def on_epoch_end(self, epoch, logs=None):
|
| 905 |
+
logs["learning_rate"] = keras.ops.convert_to_numpy(model.optimizer.learning_rate)
|
| 906 |
+
for dataloader in dev_dataloaders + (test_dataloaders if epoch + 1 == args.epochs + args.epochs_frozen else []):
|
| 907 |
+
_, metrics = model.evaluate(dataloader, save_as=os.path.splitext(
|
| 908 |
+
os.path.join(args.logdir, os.path.basename(dataloader.dataset.ud_dataset.path))
|
| 909 |
+
)[0] + ".{:02d}.conllu".format(epoch + 1))
|
| 910 |
+
for metric, score in metrics.items():
|
| 911 |
+
if metric in self._metrics:
|
| 912 |
+
logs["{}_{}".format(os.path.splitext(os.path.basename(dataloader.dataset.ud_dataset.path))[0], metric)] = 100 * score.f1
|
| 913 |
+
|
| 914 |
+
aggregations = {"la_ud213": [("la_ittb-ud", 390_787), ("la_llct-ud", 194_143), ("la_proiel-ud", 177_558),
|
| 915 |
+
("la_udante-ud", 30_450), ("la_perseus-ud", 16_486)]}
|
| 916 |
+
for split in ["dev", "test"]:
|
| 917 |
+
for metric in self._metrics:
|
| 918 |
+
for aggregation, parts in aggregations.items():
|
| 919 |
+
values = [logs.get("{}-{}_{}".format(part, split, metric), None) for part, _ in parts]
|
| 920 |
+
if all(value is not None for value in values):
|
| 921 |
+
logs["{}-{}_{}".format(aggregation, split, metric)] = np.mean(values)
|
| 922 |
+
logs["{}-sqrt-{}_{}".format(aggregation, split, metric)] = np.average(values, weights=[size**0.5 for _, size in parts])
|
| 923 |
+
|
| 924 |
+
if self._wandb_log:
|
| 925 |
+
self._wandb_log(logs, step=epoch + 1, commit=True)
|
| 926 |
+
|
| 927 |
+
wandb_log = None
|
| 928 |
+
if args.wandb:
|
| 929 |
+
import wandb
|
| 930 |
+
wandb.init(project="ufal-evalatin2024", name=args.exp, config=vars(args))
|
| 931 |
+
wandb_log = wandb.log
|
| 932 |
+
evaluator = Evaluator(wandb_log)
|
| 933 |
+
if args.epochs_frozen:
|
| 934 |
+
model.compile(len(train_dataloader), frozen=True)
|
| 935 |
+
model.fit(train_dataloader, epochs=args.epochs_frozen, verbose=args.verbose, callbacks=[evaluator])
|
| 936 |
+
if args.epochs:
|
| 937 |
+
model.compile(len(train_dataloader), frozen=False)
|
| 938 |
+
model.fit(train_dataloader, initial_epoch=args.epochs_frozen, epochs=args.epochs_frozen + args.epochs, verbose=args.verbose, callbacks=[evaluator])
|
| 939 |
+
if args.save_checkpoint:
|
| 940 |
+
model.save_weights(os.path.join(args.logdir, "model.weights.h5"))
|
| 941 |
+
|
| 942 |
+
|
| 943 |
+
if __name__ == "__main__":
|
| 944 |
+
main([] if "__file__" not in globals() else None)
|
src/evalatin2024-latinpipe/latinpipe_evalatin24_eval.py
ADDED
|
@@ -0,0 +1,596 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python
|
| 2 |
+
|
| 3 |
+
# Compatible with Python 2.7 and 3.2+, can be used either as a module
|
| 4 |
+
# or a standalone executable.
|
| 5 |
+
#
|
| 6 |
+
# Copyright 2017, 2018 Institute of Formal and Applied Linguistics (UFAL),
|
| 7 |
+
# Faculty of Mathematics and Physics, Charles University, Czech Republic.
|
| 8 |
+
#
|
| 9 |
+
# This Source Code Form is subject to the terms of the Mozilla Public
|
| 10 |
+
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
| 11 |
+
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
| 12 |
+
#
|
| 13 |
+
# Authors: Milan Straka, Martin Popel <[email protected]>
|
| 14 |
+
#
|
| 15 |
+
# Changelog:
|
| 16 |
+
# - [12 Apr 2018] Version 0.9: Initial release.
|
| 17 |
+
# - [19 Apr 2018] Version 1.0: Fix bug in MLAS (duplicate entries in functional_children).
|
| 18 |
+
# Add --counts option.
|
| 19 |
+
# - [02 May 2018] Version 1.1: When removing spaces to match gold and system characters,
|
| 20 |
+
# consider all Unicode characters of category Zs instead of
|
| 21 |
+
# just ASCII space.
|
| 22 |
+
# - [12 Sep 2020] Version 1.2: Renamed to udpipe2_eval when releasing with UDPipe 2
|
| 23 |
+
# Allow evaluation with underscores in HEAD.
|
| 24 |
+
# - [26 Jul 2022] Version 1.3: Allow evaluation with multiple roots, if requested.
|
| 25 |
+
# - [13 Jan 2024] Version 1.4: Renamed to udpipe_evalatin24_eval when releasing with
|
| 26 |
+
# UDPipe EvaLatin 24.
|
| 27 |
+
|
| 28 |
+
# Command line usage
|
| 29 |
+
# ------------------
|
| 30 |
+
# udpipe_evalatin24_eval.py [-v] gold_conllu_file system_conllu_file
|
| 31 |
+
#
|
| 32 |
+
# - if no -v is given, only the official CoNLL18 UD Shared Task evaluation metrics
|
| 33 |
+
# are printed
|
| 34 |
+
# - if -v is given, more metrics are printed (as precision, recall, F1 score,
|
| 35 |
+
# and in case the metric is computed on aligned words also accuracy on these):
|
| 36 |
+
# - Tokens: how well do the gold tokens match system tokens
|
| 37 |
+
# - Sentences: how well do the gold sentences match system sentences
|
| 38 |
+
# - Words: how well can the gold words be aligned to system words
|
| 39 |
+
# - UPOS: using aligned words, how well does UPOS match
|
| 40 |
+
# - XPOS: using aligned words, how well does XPOS match
|
| 41 |
+
# - UFeats: using aligned words, how well does universal FEATS match
|
| 42 |
+
# - AllTags: using aligned words, how well does UPOS+XPOS+FEATS match
|
| 43 |
+
# - Lemmas: using aligned words, how well does LEMMA match
|
| 44 |
+
# - UAS: using aligned words, how well does HEAD match
|
| 45 |
+
# - LAS: using aligned words, how well does HEAD+DEPREL(ignoring subtypes) match
|
| 46 |
+
# - CLAS: using aligned words with content DEPREL, how well does
|
| 47 |
+
# HEAD+DEPREL(ignoring subtypes) match
|
| 48 |
+
# - MLAS: using aligned words with content DEPREL, how well does
|
| 49 |
+
# HEAD+DEPREL(ignoring subtypes)+UPOS+UFEATS+FunctionalChildren(DEPREL+UPOS+UFEATS) match
|
| 50 |
+
# - BLEX: using aligned words with content DEPREL, how well does
|
| 51 |
+
# HEAD+DEPREL(ignoring subtypes)+LEMMAS match
|
| 52 |
+
# - if -c is given, raw counts of correct/gold_total/system_total/aligned words are printed
|
| 53 |
+
# instead of precision/recall/F1/AlignedAccuracy for all metrics.
|
| 54 |
+
|
| 55 |
+
# API usage
|
| 56 |
+
# ---------
|
| 57 |
+
# - load_conllu(file)
|
| 58 |
+
# - loads CoNLL-U file from given file object to an internal representation
|
| 59 |
+
# - the file object should return str in both Python 2 and Python 3
|
| 60 |
+
# - raises UDError exception if the given file cannot be loaded
|
| 61 |
+
# - evaluate(gold_ud, system_ud)
|
| 62 |
+
# - evaluate the given gold and system CoNLL-U files (loaded with load_conllu)
|
| 63 |
+
# - raises UDError if the concatenated tokens of gold and system file do not match
|
| 64 |
+
# - returns a dictionary with the metrics described above, each metric having
|
| 65 |
+
# three fields: precision, recall and f1
|
| 66 |
+
|
| 67 |
+
# Description of token matching
|
| 68 |
+
# -----------------------------
|
| 69 |
+
# In order to match tokens of gold file and system file, we consider the text
|
| 70 |
+
# resulting from concatenation of gold tokens and text resulting from
|
| 71 |
+
# concatenation of system tokens. These texts should match -- if they do not,
|
| 72 |
+
# the evaluation fails.
|
| 73 |
+
#
|
| 74 |
+
# If the texts do match, every token is represented as a range in this original
|
| 75 |
+
# text, and tokens are equal only if their range is the same.
|
| 76 |
+
|
| 77 |
+
# Description of word matching
|
| 78 |
+
# ----------------------------
|
| 79 |
+
# When matching words of gold file and system file, we first match the tokens.
|
| 80 |
+
# The words which are also tokens are matched as tokens, but words in multi-word
|
| 81 |
+
# tokens have to be handled differently.
|
| 82 |
+
#
|
| 83 |
+
# To handle multi-word tokens, we start by finding "multi-word spans".
|
| 84 |
+
# Multi-word span is a span in the original text such that
|
| 85 |
+
# - it contains at least one multi-word token
|
| 86 |
+
# - all multi-word tokens in the span (considering both gold and system ones)
|
| 87 |
+
# are completely inside the span (i.e., they do not "stick out")
|
| 88 |
+
# - the multi-word span is as small as possible
|
| 89 |
+
#
|
| 90 |
+
# For every multi-word span, we align the gold and system words completely
|
| 91 |
+
# inside this span using LCS on their FORMs. The words not intersecting
|
| 92 |
+
# (even partially) any multi-word span are then aligned as tokens.
|
| 93 |
+
|
| 94 |
+
|
| 95 |
+
from __future__ import division
|
| 96 |
+
from __future__ import print_function
|
| 97 |
+
|
| 98 |
+
import argparse
|
| 99 |
+
import io
|
| 100 |
+
import sys
|
| 101 |
+
import unicodedata
|
| 102 |
+
import unittest
|
| 103 |
+
|
| 104 |
+
__version__ = "2.1.1-dev"
|
| 105 |
+
|
| 106 |
+
|
| 107 |
+
# CoNLL-U column names
|
| 108 |
+
ID, FORM, LEMMA, UPOS, XPOS, FEATS, HEAD, DEPREL, DEPS, MISC = range(10)
|
| 109 |
+
|
| 110 |
+
# Content and functional relations
|
| 111 |
+
CONTENT_DEPRELS = {
|
| 112 |
+
"nsubj", "obj", "iobj", "csubj", "ccomp", "xcomp", "obl", "vocative",
|
| 113 |
+
"expl", "dislocated", "advcl", "advmod", "discourse", "nmod", "appos",
|
| 114 |
+
"nummod", "acl", "amod", "conj", "fixed", "flat", "compound", "list",
|
| 115 |
+
"parataxis", "orphan", "goeswith", "reparandum", "root", "dep"
|
| 116 |
+
}
|
| 117 |
+
|
| 118 |
+
FUNCTIONAL_DEPRELS = {
|
| 119 |
+
"aux", "cop", "mark", "det", "clf", "case", "cc"
|
| 120 |
+
}
|
| 121 |
+
|
| 122 |
+
UNIVERSAL_FEATURES = {
|
| 123 |
+
"PronType", "NumType", "Poss", "Reflex", "Foreign", "Abbr", "Gender",
|
| 124 |
+
"Animacy", "Number", "Case", "Definite", "Degree", "VerbForm", "Mood",
|
| 125 |
+
"Tense", "Aspect", "Voice", "Evident", "Polarity", "Person", "Polite"
|
| 126 |
+
}
|
| 127 |
+
|
| 128 |
+
# UD Error is used when raising exceptions in this module
|
| 129 |
+
class UDError(Exception):
|
| 130 |
+
pass
|
| 131 |
+
|
| 132 |
+
# Load given CoNLL-U file into internal representation
|
| 133 |
+
def load_conllu(file, single_root=1):
|
| 134 |
+
# Internal representation classes
|
| 135 |
+
class UDRepresentation:
|
| 136 |
+
def __init__(self):
|
| 137 |
+
# Characters of all the tokens in the whole file.
|
| 138 |
+
# Whitespace between tokens is not included.
|
| 139 |
+
self.characters = []
|
| 140 |
+
# List of UDSpan instances with start&end indices into `characters`.
|
| 141 |
+
self.tokens = []
|
| 142 |
+
# List of UDWord instances.
|
| 143 |
+
self.words = []
|
| 144 |
+
# List of UDSpan instances with start&end indices into `characters`.
|
| 145 |
+
self.sentences = []
|
| 146 |
+
class UDSpan:
|
| 147 |
+
def __init__(self, start, end):
|
| 148 |
+
self.start = start
|
| 149 |
+
# Note that self.end marks the first position **after the end** of span,
|
| 150 |
+
# so we can use characters[start:end] or range(start, end).
|
| 151 |
+
self.end = end
|
| 152 |
+
class UDWord:
|
| 153 |
+
def __init__(self, span, columns, is_multiword):
|
| 154 |
+
# Span of this word (or MWT, see below) within ud_representation.characters.
|
| 155 |
+
self.span = span
|
| 156 |
+
# 10 columns of the CoNLL-U file: ID, FORM, LEMMA,...
|
| 157 |
+
self.columns = columns
|
| 158 |
+
# is_multiword==True means that this word is part of a multi-word token.
|
| 159 |
+
# In that case, self.span marks the span of the whole multi-word token.
|
| 160 |
+
self.is_multiword = is_multiword
|
| 161 |
+
# Reference to the UDWord instance representing the HEAD (or None if root).
|
| 162 |
+
self.parent = None
|
| 163 |
+
# List of references to UDWord instances representing functional-deprel children.
|
| 164 |
+
self.functional_children = []
|
| 165 |
+
# Only consider universal FEATS.
|
| 166 |
+
self.columns[FEATS] = "|".join(sorted(feat for feat in columns[FEATS].split("|")
|
| 167 |
+
if feat.split("=", 1)[0] in UNIVERSAL_FEATURES))
|
| 168 |
+
# Let's ignore language-specific deprel subtypes.
|
| 169 |
+
self.columns[DEPREL] = columns[DEPREL].split(":")[0]
|
| 170 |
+
# Precompute which deprels are CONTENT_DEPRELS and which FUNCTIONAL_DEPRELS
|
| 171 |
+
self.is_content_deprel = self.columns[DEPREL] in CONTENT_DEPRELS
|
| 172 |
+
self.is_functional_deprel = self.columns[DEPREL] in FUNCTIONAL_DEPRELS
|
| 173 |
+
|
| 174 |
+
ud = UDRepresentation()
|
| 175 |
+
|
| 176 |
+
# Load the CoNLL-U file
|
| 177 |
+
index, sentence_start = 0, None
|
| 178 |
+
while True:
|
| 179 |
+
line = file.readline()
|
| 180 |
+
if not line:
|
| 181 |
+
break
|
| 182 |
+
line = line.rstrip("\r\n")
|
| 183 |
+
|
| 184 |
+
# Handle sentence start boundaries
|
| 185 |
+
if sentence_start is None:
|
| 186 |
+
# Skip comments
|
| 187 |
+
if line.startswith("#"):
|
| 188 |
+
continue
|
| 189 |
+
# Start a new sentence
|
| 190 |
+
ud.sentences.append(UDSpan(index, 0))
|
| 191 |
+
sentence_start = len(ud.words)
|
| 192 |
+
if not line:
|
| 193 |
+
# Add parent and children UDWord links and check there are no cycles
|
| 194 |
+
def process_word(word):
|
| 195 |
+
if word.parent == "remapping":
|
| 196 |
+
raise UDError("There is a cycle in a sentence")
|
| 197 |
+
if word.parent is None:
|
| 198 |
+
if word.columns[HEAD] == "_":
|
| 199 |
+
word.parent = "missing"
|
| 200 |
+
else:
|
| 201 |
+
head = int(word.columns[HEAD])
|
| 202 |
+
if head < 0 or head > len(ud.words) - sentence_start:
|
| 203 |
+
raise UDError("HEAD '{}' points outside of the sentence".format(word.columns[HEAD]))
|
| 204 |
+
if head:
|
| 205 |
+
parent = ud.words[sentence_start + head - 1]
|
| 206 |
+
word.parent = "remapping"
|
| 207 |
+
process_word(parent)
|
| 208 |
+
word.parent = parent
|
| 209 |
+
|
| 210 |
+
for word in ud.words[sentence_start:]:
|
| 211 |
+
process_word(word)
|
| 212 |
+
# func_children cannot be assigned within process_word
|
| 213 |
+
# because it is called recursively and may result in adding one child twice.
|
| 214 |
+
for word in ud.words[sentence_start:]:
|
| 215 |
+
if word.parent and word.is_functional_deprel:
|
| 216 |
+
word.parent.functional_children.append(word)
|
| 217 |
+
|
| 218 |
+
# Check there is a single root node
|
| 219 |
+
if single_root:
|
| 220 |
+
if len([word for word in ud.words[sentence_start:] if word.parent is None]) > 1:
|
| 221 |
+
raise UDError("There are multiple roots in a sentence")
|
| 222 |
+
|
| 223 |
+
# End the sentence
|
| 224 |
+
ud.sentences[-1].end = index
|
| 225 |
+
sentence_start = None
|
| 226 |
+
continue
|
| 227 |
+
|
| 228 |
+
# Read next token/word
|
| 229 |
+
columns = line.split("\t")
|
| 230 |
+
if len(columns) != 10:
|
| 231 |
+
raise UDError("The CoNLL-U line does not contain 10 tab-separated columns: '{}'".format(line))
|
| 232 |
+
|
| 233 |
+
# Skip empty nodes
|
| 234 |
+
if "." in columns[ID]:
|
| 235 |
+
continue
|
| 236 |
+
|
| 237 |
+
# Delete spaces from FORM, so gold.characters == system.characters
|
| 238 |
+
# even if one of them tokenizes the space. Use any Unicode character
|
| 239 |
+
# with category Zs.
|
| 240 |
+
if sys.version_info < (3, 0) and isinstance(line, str):
|
| 241 |
+
columns[FORM] = columns[FORM].decode("utf-8")
|
| 242 |
+
columns[FORM] = "".join(filter(lambda c: unicodedata.category(c) != "Zs", columns[FORM]))
|
| 243 |
+
if sys.version_info < (3, 0) and isinstance(line, str):
|
| 244 |
+
columns[FORM] = columns[FORM].encode("utf-8")
|
| 245 |
+
if not columns[FORM]:
|
| 246 |
+
raise UDError("There is an empty FORM in the CoNLL-U file")
|
| 247 |
+
|
| 248 |
+
# Save token
|
| 249 |
+
ud.characters.extend(columns[FORM])
|
| 250 |
+
ud.tokens.append(UDSpan(index, index + len(columns[FORM])))
|
| 251 |
+
index += len(columns[FORM])
|
| 252 |
+
|
| 253 |
+
# Handle multi-word tokens to save word(s)
|
| 254 |
+
if "-" in columns[ID]:
|
| 255 |
+
try:
|
| 256 |
+
start, end = map(int, columns[ID].split("-"))
|
| 257 |
+
except:
|
| 258 |
+
raise UDError("Cannot parse multi-word token ID '{}'".format(columns[ID]))
|
| 259 |
+
|
| 260 |
+
for _ in range(start, end + 1):
|
| 261 |
+
word_line = file.readline().rstrip("\r\n")
|
| 262 |
+
word_columns = word_line.split("\t")
|
| 263 |
+
if len(word_columns) != 10:
|
| 264 |
+
raise UDError("The CoNLL-U line does not contain 10 tab-separated columns: '{}'".format(word_line))
|
| 265 |
+
ud.words.append(UDWord(ud.tokens[-1], word_columns, is_multiword=True))
|
| 266 |
+
# Basic tokens/words
|
| 267 |
+
else:
|
| 268 |
+
try:
|
| 269 |
+
word_id = int(columns[ID])
|
| 270 |
+
except:
|
| 271 |
+
raise UDError("Cannot parse word ID '{}'".format(columns[ID]))
|
| 272 |
+
if word_id != len(ud.words) - sentence_start + 1:
|
| 273 |
+
raise UDError("Incorrect word ID '{}' for word '{}', expected '{}'".format(columns[ID], columns[FORM], len(ud.words) - sentence_start + 1))
|
| 274 |
+
|
| 275 |
+
if columns[HEAD] != "_":
|
| 276 |
+
try:
|
| 277 |
+
head_id = int(columns[HEAD])
|
| 278 |
+
except:
|
| 279 |
+
raise UDError("Cannot parse HEAD '{}'".format(columns[HEAD]))
|
| 280 |
+
if head_id < 0:
|
| 281 |
+
raise UDError("HEAD cannot be negative")
|
| 282 |
+
|
| 283 |
+
ud.words.append(UDWord(ud.tokens[-1], columns, is_multiword=False))
|
| 284 |
+
|
| 285 |
+
if sentence_start is not None:
|
| 286 |
+
raise UDError("The CoNLL-U file does not end with empty line")
|
| 287 |
+
|
| 288 |
+
return ud
|
| 289 |
+
|
| 290 |
+
# Evaluate the gold and system treebanks (loaded using load_conllu).
|
| 291 |
+
def evaluate(gold_ud, system_ud):
|
| 292 |
+
class Score:
|
| 293 |
+
def __init__(self, gold_total, system_total, correct, aligned_total=None):
|
| 294 |
+
self.correct = correct
|
| 295 |
+
self.gold_total = gold_total
|
| 296 |
+
self.system_total = system_total
|
| 297 |
+
self.aligned_total = aligned_total
|
| 298 |
+
self.precision = correct / system_total if system_total else 0.0
|
| 299 |
+
self.recall = correct / gold_total if gold_total else 0.0
|
| 300 |
+
self.f1 = 2 * correct / (system_total + gold_total) if system_total + gold_total else 0.0
|
| 301 |
+
self.aligned_accuracy = correct / aligned_total if aligned_total else aligned_total
|
| 302 |
+
class AlignmentWord:
|
| 303 |
+
def __init__(self, gold_word, system_word):
|
| 304 |
+
self.gold_word = gold_word
|
| 305 |
+
self.system_word = system_word
|
| 306 |
+
class Alignment:
|
| 307 |
+
def __init__(self, gold_words, system_words):
|
| 308 |
+
self.gold_words = gold_words
|
| 309 |
+
self.system_words = system_words
|
| 310 |
+
self.matched_words = []
|
| 311 |
+
self.matched_words_map = {}
|
| 312 |
+
def append_aligned_words(self, gold_word, system_word):
|
| 313 |
+
self.matched_words.append(AlignmentWord(gold_word, system_word))
|
| 314 |
+
self.matched_words_map[system_word] = gold_word
|
| 315 |
+
|
| 316 |
+
def lower(text):
|
| 317 |
+
if sys.version_info < (3, 0) and isinstance(text, str):
|
| 318 |
+
return text.decode("utf-8").lower()
|
| 319 |
+
return text.lower()
|
| 320 |
+
|
| 321 |
+
def spans_score(gold_spans, system_spans):
|
| 322 |
+
correct, gi, si = 0, 0, 0
|
| 323 |
+
while gi < len(gold_spans) and si < len(system_spans):
|
| 324 |
+
if system_spans[si].start < gold_spans[gi].start:
|
| 325 |
+
si += 1
|
| 326 |
+
elif gold_spans[gi].start < system_spans[si].start:
|
| 327 |
+
gi += 1
|
| 328 |
+
else:
|
| 329 |
+
correct += gold_spans[gi].end == system_spans[si].end
|
| 330 |
+
si += 1
|
| 331 |
+
gi += 1
|
| 332 |
+
|
| 333 |
+
return Score(len(gold_spans), len(system_spans), correct)
|
| 334 |
+
|
| 335 |
+
def alignment_score(alignment, key_fn=None, filter_fn=None):
|
| 336 |
+
if filter_fn is not None:
|
| 337 |
+
gold = sum(1 for gold in alignment.gold_words if filter_fn(gold))
|
| 338 |
+
system = sum(1 for system in alignment.system_words if filter_fn(system))
|
| 339 |
+
aligned = sum(1 for word in alignment.matched_words if filter_fn(word.gold_word))
|
| 340 |
+
else:
|
| 341 |
+
gold = len(alignment.gold_words)
|
| 342 |
+
system = len(alignment.system_words)
|
| 343 |
+
aligned = len(alignment.matched_words)
|
| 344 |
+
|
| 345 |
+
if key_fn is None:
|
| 346 |
+
# Return score for whole aligned words
|
| 347 |
+
return Score(gold, system, aligned)
|
| 348 |
+
|
| 349 |
+
def gold_aligned_gold(word):
|
| 350 |
+
return word
|
| 351 |
+
def gold_aligned_system(word):
|
| 352 |
+
return alignment.matched_words_map.get(word, "NotAligned") if word is not None else None
|
| 353 |
+
correct = 0
|
| 354 |
+
for words in alignment.matched_words:
|
| 355 |
+
if filter_fn is None or filter_fn(words.gold_word):
|
| 356 |
+
if key_fn(words.gold_word, gold_aligned_gold) == key_fn(words.system_word, gold_aligned_system):
|
| 357 |
+
correct += 1
|
| 358 |
+
|
| 359 |
+
return Score(gold, system, correct, aligned)
|
| 360 |
+
|
| 361 |
+
def beyond_end(words, i, multiword_span_end):
|
| 362 |
+
if i >= len(words):
|
| 363 |
+
return True
|
| 364 |
+
if words[i].is_multiword:
|
| 365 |
+
return words[i].span.start >= multiword_span_end
|
| 366 |
+
return words[i].span.end > multiword_span_end
|
| 367 |
+
|
| 368 |
+
def extend_end(word, multiword_span_end):
|
| 369 |
+
if word.is_multiword and word.span.end > multiword_span_end:
|
| 370 |
+
return word.span.end
|
| 371 |
+
return multiword_span_end
|
| 372 |
+
|
| 373 |
+
def find_multiword_span(gold_words, system_words, gi, si):
|
| 374 |
+
# We know gold_words[gi].is_multiword or system_words[si].is_multiword.
|
| 375 |
+
# Find the start of the multiword span (gs, ss), so the multiword span is minimal.
|
| 376 |
+
# Initialize multiword_span_end characters index.
|
| 377 |
+
if gold_words[gi].is_multiword:
|
| 378 |
+
multiword_span_end = gold_words[gi].span.end
|
| 379 |
+
if not system_words[si].is_multiword and system_words[si].span.start < gold_words[gi].span.start:
|
| 380 |
+
si += 1
|
| 381 |
+
else: # if system_words[si].is_multiword
|
| 382 |
+
multiword_span_end = system_words[si].span.end
|
| 383 |
+
if not gold_words[gi].is_multiword and gold_words[gi].span.start < system_words[si].span.start:
|
| 384 |
+
gi += 1
|
| 385 |
+
gs, ss = gi, si
|
| 386 |
+
|
| 387 |
+
# Find the end of the multiword span
|
| 388 |
+
# (so both gi and si are pointing to the word following the multiword span end).
|
| 389 |
+
while not beyond_end(gold_words, gi, multiword_span_end) or \
|
| 390 |
+
not beyond_end(system_words, si, multiword_span_end):
|
| 391 |
+
if gi < len(gold_words) and (si >= len(system_words) or
|
| 392 |
+
gold_words[gi].span.start <= system_words[si].span.start):
|
| 393 |
+
multiword_span_end = extend_end(gold_words[gi], multiword_span_end)
|
| 394 |
+
gi += 1
|
| 395 |
+
else:
|
| 396 |
+
multiword_span_end = extend_end(system_words[si], multiword_span_end)
|
| 397 |
+
si += 1
|
| 398 |
+
return gs, ss, gi, si
|
| 399 |
+
|
| 400 |
+
def compute_lcs(gold_words, system_words, gi, si, gs, ss):
|
| 401 |
+
lcs = [[0] * (si - ss) for i in range(gi - gs)]
|
| 402 |
+
for g in reversed(range(gi - gs)):
|
| 403 |
+
for s in reversed(range(si - ss)):
|
| 404 |
+
if lower(gold_words[gs + g].columns[FORM]) == lower(system_words[ss + s].columns[FORM]):
|
| 405 |
+
lcs[g][s] = 1 + (lcs[g+1][s+1] if g+1 < gi-gs and s+1 < si-ss else 0)
|
| 406 |
+
lcs[g][s] = max(lcs[g][s], lcs[g+1][s] if g+1 < gi-gs else 0)
|
| 407 |
+
lcs[g][s] = max(lcs[g][s], lcs[g][s+1] if s+1 < si-ss else 0)
|
| 408 |
+
return lcs
|
| 409 |
+
|
| 410 |
+
def align_words(gold_words, system_words):
|
| 411 |
+
alignment = Alignment(gold_words, system_words)
|
| 412 |
+
|
| 413 |
+
gi, si = 0, 0
|
| 414 |
+
while gi < len(gold_words) and si < len(system_words):
|
| 415 |
+
if gold_words[gi].is_multiword or system_words[si].is_multiword:
|
| 416 |
+
# A: Multi-word tokens => align via LCS within the whole "multiword span".
|
| 417 |
+
gs, ss, gi, si = find_multiword_span(gold_words, system_words, gi, si)
|
| 418 |
+
|
| 419 |
+
if si > ss and gi > gs:
|
| 420 |
+
lcs = compute_lcs(gold_words, system_words, gi, si, gs, ss)
|
| 421 |
+
|
| 422 |
+
# Store aligned words
|
| 423 |
+
s, g = 0, 0
|
| 424 |
+
while g < gi - gs and s < si - ss:
|
| 425 |
+
if lower(gold_words[gs + g].columns[FORM]) == lower(system_words[ss + s].columns[FORM]):
|
| 426 |
+
alignment.append_aligned_words(gold_words[gs+g], system_words[ss+s])
|
| 427 |
+
g += 1
|
| 428 |
+
s += 1
|
| 429 |
+
elif lcs[g][s] == (lcs[g+1][s] if g+1 < gi-gs else 0):
|
| 430 |
+
g += 1
|
| 431 |
+
else:
|
| 432 |
+
s += 1
|
| 433 |
+
else:
|
| 434 |
+
# B: No multi-word token => align according to spans.
|
| 435 |
+
if (gold_words[gi].span.start, gold_words[gi].span.end) == (system_words[si].span.start, system_words[si].span.end):
|
| 436 |
+
alignment.append_aligned_words(gold_words[gi], system_words[si])
|
| 437 |
+
gi += 1
|
| 438 |
+
si += 1
|
| 439 |
+
elif gold_words[gi].span.start <= system_words[si].span.start:
|
| 440 |
+
gi += 1
|
| 441 |
+
else:
|
| 442 |
+
si += 1
|
| 443 |
+
|
| 444 |
+
return alignment
|
| 445 |
+
|
| 446 |
+
# Check that the underlying character sequences do match.
|
| 447 |
+
if gold_ud.characters != system_ud.characters:
|
| 448 |
+
index = 0
|
| 449 |
+
while index < len(gold_ud.characters) and index < len(system_ud.characters) and \
|
| 450 |
+
gold_ud.characters[index] == system_ud.characters[index]:
|
| 451 |
+
index += 1
|
| 452 |
+
|
| 453 |
+
raise UDError(
|
| 454 |
+
"The concatenation of tokens in gold file and in system file differ!\n" +
|
| 455 |
+
"First 20 differing characters in gold file: '{}' and system file: '{}'".format(
|
| 456 |
+
"".join(gold_ud.characters[index:index + 20]),
|
| 457 |
+
"".join(system_ud.characters[index:index + 20])
|
| 458 |
+
)
|
| 459 |
+
)
|
| 460 |
+
|
| 461 |
+
# Align words
|
| 462 |
+
alignment = align_words(gold_ud.words, system_ud.words)
|
| 463 |
+
|
| 464 |
+
# Compute the F1-scores
|
| 465 |
+
return {
|
| 466 |
+
"Tokens": spans_score(gold_ud.tokens, system_ud.tokens),
|
| 467 |
+
"Sentences": spans_score(gold_ud.sentences, system_ud.sentences),
|
| 468 |
+
"Words": alignment_score(alignment),
|
| 469 |
+
"UPOS": alignment_score(alignment, lambda w, _: w.columns[UPOS]),
|
| 470 |
+
"XPOS": alignment_score(alignment, lambda w, _: w.columns[XPOS]),
|
| 471 |
+
"UFeats": alignment_score(alignment, lambda w, _: w.columns[FEATS]),
|
| 472 |
+
"AllTags": alignment_score(alignment, lambda w, _: (w.columns[UPOS], w.columns[XPOS], w.columns[FEATS])),
|
| 473 |
+
"Lemmas": alignment_score(alignment, lambda w, ga: w.columns[LEMMA] if ga(w).columns[LEMMA] != "_" else "_"),
|
| 474 |
+
"UAS": alignment_score(alignment, lambda w, ga: ga(w.parent)),
|
| 475 |
+
"LAS": alignment_score(alignment, lambda w, ga: (ga(w.parent), w.columns[DEPREL])),
|
| 476 |
+
"CLAS": alignment_score(alignment, lambda w, ga: (ga(w.parent), w.columns[DEPREL]),
|
| 477 |
+
filter_fn=lambda w: w.is_content_deprel),
|
| 478 |
+
"MLAS": alignment_score(alignment, lambda w, ga: (ga(w.parent), w.columns[DEPREL], w.columns[UPOS], w.columns[FEATS],
|
| 479 |
+
[(ga(c), c.columns[DEPREL], c.columns[UPOS], c.columns[FEATS])
|
| 480 |
+
for c in w.functional_children]),
|
| 481 |
+
filter_fn=lambda w: w.is_content_deprel),
|
| 482 |
+
"BLEX": alignment_score(alignment, lambda w, ga: (ga(w.parent), w.columns[DEPREL],
|
| 483 |
+
w.columns[LEMMA] if ga(w).columns[LEMMA] != "_" else "_"),
|
| 484 |
+
filter_fn=lambda w: w.is_content_deprel),
|
| 485 |
+
}
|
| 486 |
+
|
| 487 |
+
|
| 488 |
+
def load_conllu_file(path, single_root=1):
|
| 489 |
+
_file = open(path, mode="r", **({"encoding": "utf-8"} if sys.version_info >= (3, 0) else {}))
|
| 490 |
+
return load_conllu(_file, single_root)
|
| 491 |
+
|
| 492 |
+
def evaluate_wrapper(args):
|
| 493 |
+
# Load CoNLL-U files
|
| 494 |
+
gold_ud = load_conllu_file(args.gold_file, args.single_root)
|
| 495 |
+
system_ud = load_conllu_file(args.system_file, args.single_root)
|
| 496 |
+
return evaluate(gold_ud, system_ud)
|
| 497 |
+
|
| 498 |
+
def main():
|
| 499 |
+
# Parse arguments
|
| 500 |
+
parser = argparse.ArgumentParser()
|
| 501 |
+
parser.add_argument("gold_file", type=str,
|
| 502 |
+
help="Name of the CoNLL-U file with the gold data.")
|
| 503 |
+
parser.add_argument("system_file", type=str,
|
| 504 |
+
help="Name of the CoNLL-U file with the predicted data.")
|
| 505 |
+
parser.add_argument("--verbose", "-v", default=False, action="store_true",
|
| 506 |
+
help="Print all metrics.")
|
| 507 |
+
parser.add_argument("--counts", "-c", default=False, action="store_true",
|
| 508 |
+
help="Print raw counts of correct/gold/system/aligned words instead of prec/rec/F1 for all metrics.")
|
| 509 |
+
parser.add_argument("--no_single_root", dest="single_root", default=True, action="store_false",
|
| 510 |
+
help="Allow multiple roots in a sentence.")
|
| 511 |
+
args = parser.parse_args()
|
| 512 |
+
|
| 513 |
+
# Evaluate
|
| 514 |
+
evaluation = evaluate_wrapper(args)
|
| 515 |
+
|
| 516 |
+
# Print the evaluation
|
| 517 |
+
if not args.verbose and not args.counts:
|
| 518 |
+
print("LAS F1 Score: {:.2f}".format(100 * evaluation["LAS"].f1))
|
| 519 |
+
print("MLAS Score: {:.2f}".format(100 * evaluation["MLAS"].f1))
|
| 520 |
+
print("BLEX Score: {:.2f}".format(100 * evaluation["BLEX"].f1))
|
| 521 |
+
else:
|
| 522 |
+
if args.counts:
|
| 523 |
+
print("Metric | Correct | Gold | Predicted | Aligned")
|
| 524 |
+
else:
|
| 525 |
+
print("Metric | Precision | Recall | F1 Score | AligndAcc")
|
| 526 |
+
print("-----------+-----------+-----------+-----------+-----------")
|
| 527 |
+
for metric in["Tokens", "Sentences", "Words", "UPOS", "XPOS", "UFeats", "AllTags", "Lemmas", "UAS", "LAS", "CLAS", "MLAS", "BLEX"]:
|
| 528 |
+
if args.counts:
|
| 529 |
+
print("{:11}|{:10} |{:10} |{:10} |{:10}".format(
|
| 530 |
+
metric,
|
| 531 |
+
evaluation[metric].correct,
|
| 532 |
+
evaluation[metric].gold_total,
|
| 533 |
+
evaluation[metric].system_total,
|
| 534 |
+
evaluation[metric].aligned_total or (evaluation[metric].correct if metric == "Words" else "")
|
| 535 |
+
))
|
| 536 |
+
else:
|
| 537 |
+
print("{:11}|{:10.2f} |{:10.2f} |{:10.2f} |{}".format(
|
| 538 |
+
metric,
|
| 539 |
+
100 * evaluation[metric].precision,
|
| 540 |
+
100 * evaluation[metric].recall,
|
| 541 |
+
100 * evaluation[metric].f1,
|
| 542 |
+
"{:10.2f}".format(100 * evaluation[metric].aligned_accuracy) if evaluation[metric].aligned_accuracy is not None else ""
|
| 543 |
+
))
|
| 544 |
+
|
| 545 |
+
if __name__ == "__main__":
|
| 546 |
+
main()
|
| 547 |
+
|
| 548 |
+
# Tests, which can be executed with `python -m unittest udpipe_evalatin24_eval`.
|
| 549 |
+
class TestAlignment(unittest.TestCase):
|
| 550 |
+
@staticmethod
|
| 551 |
+
def _load_words(words):
|
| 552 |
+
"""Prepare fake CoNLL-U files with fake HEAD to prevent multiple roots errors."""
|
| 553 |
+
lines, num_words = [], 0
|
| 554 |
+
for w in words:
|
| 555 |
+
parts = w.split(" ")
|
| 556 |
+
if len(parts) == 1:
|
| 557 |
+
num_words += 1
|
| 558 |
+
lines.append("{}\t{}\t_\t_\t_\t_\t{}\t_\t_\t_".format(num_words, parts[0], int(num_words>1)))
|
| 559 |
+
else:
|
| 560 |
+
lines.append("{}-{}\t{}\t_\t_\t_\t_\t_\t_\t_\t_".format(num_words + 1, num_words + len(parts) - 1, parts[0]))
|
| 561 |
+
for part in parts[1:]:
|
| 562 |
+
num_words += 1
|
| 563 |
+
lines.append("{}\t{}\t_\t_\t_\t_\t{}\t_\t_\t_".format(num_words, part, int(num_words>1)))
|
| 564 |
+
return load_conllu((io.StringIO if sys.version_info >= (3, 0) else io.BytesIO)("\n".join(lines+["\n"])))
|
| 565 |
+
|
| 566 |
+
def _test_exception(self, gold, system):
|
| 567 |
+
self.assertRaises(UDError, evaluate, self._load_words(gold), self._load_words(system))
|
| 568 |
+
|
| 569 |
+
def _test_ok(self, gold, system, correct):
|
| 570 |
+
metrics = evaluate(self._load_words(gold), self._load_words(system))
|
| 571 |
+
gold_words = sum((max(1, len(word.split(" ")) - 1) for word in gold))
|
| 572 |
+
system_words = sum((max(1, len(word.split(" ")) - 1) for word in system))
|
| 573 |
+
self.assertEqual((metrics["Words"].precision, metrics["Words"].recall, metrics["Words"].f1),
|
| 574 |
+
(correct / system_words, correct / gold_words, 2 * correct / (gold_words + system_words)))
|
| 575 |
+
|
| 576 |
+
def test_exception(self):
|
| 577 |
+
self._test_exception(["a"], ["b"])
|
| 578 |
+
|
| 579 |
+
def test_equal(self):
|
| 580 |
+
self._test_ok(["a"], ["a"], 1)
|
| 581 |
+
self._test_ok(["a", "b", "c"], ["a", "b", "c"], 3)
|
| 582 |
+
|
| 583 |
+
def test_equal_with_multiword(self):
|
| 584 |
+
self._test_ok(["abc a b c"], ["a", "b", "c"], 3)
|
| 585 |
+
self._test_ok(["a", "bc b c", "d"], ["a", "b", "c", "d"], 4)
|
| 586 |
+
self._test_ok(["abcd a b c d"], ["ab a b", "cd c d"], 4)
|
| 587 |
+
self._test_ok(["abc a b c", "de d e"], ["a", "bcd b c d", "e"], 5)
|
| 588 |
+
|
| 589 |
+
def test_alignment(self):
|
| 590 |
+
self._test_ok(["abcd"], ["a", "b", "c", "d"], 0)
|
| 591 |
+
self._test_ok(["abc", "d"], ["a", "b", "c", "d"], 1)
|
| 592 |
+
self._test_ok(["a", "bc", "d"], ["a", "b", "c", "d"], 2)
|
| 593 |
+
self._test_ok(["a", "bc b c", "d"], ["a", "b", "cd"], 2)
|
| 594 |
+
self._test_ok(["abc a BX c", "def d EX f"], ["ab a b", "cd c d", "ef e f"], 4)
|
| 595 |
+
self._test_ok(["ab a b", "cd bc d"], ["a", "bc", "d"], 2)
|
| 596 |
+
self._test_ok(["a", "bc b c", "d"], ["ab AX BX", "cd CX a"], 1)
|
src/evalatin2024-latinpipe/latinpipe_evalatin24_server.py
ADDED
|
@@ -0,0 +1,433 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
|
| 3 |
+
# This file is part of LatinPipe EvaLatin24
|
| 4 |
+
# <https://github.com/ufal/evalatin2024-latinpipe>.
|
| 5 |
+
#
|
| 6 |
+
# Copyright 2024 Institute of Formal and Applied Linguistics, Faculty of
|
| 7 |
+
# Mathematics and Physics, Charles University in Prague, Czech Republic.
|
| 8 |
+
#
|
| 9 |
+
# This Source Code Form is subject to the terms of the Mozilla Public
|
| 10 |
+
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
| 11 |
+
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
| 12 |
+
|
| 13 |
+
import argparse
|
| 14 |
+
import contextlib
|
| 15 |
+
import email.parser
|
| 16 |
+
import http.server
|
| 17 |
+
import itertools
|
| 18 |
+
import json
|
| 19 |
+
import os
|
| 20 |
+
import socketserver
|
| 21 |
+
import sys
|
| 22 |
+
import threading
|
| 23 |
+
import time
|
| 24 |
+
import unicodedata
|
| 25 |
+
import urllib.parse
|
| 26 |
+
|
| 27 |
+
import latinpipe_evalatin24
|
| 28 |
+
from latinpipe_evalatin24 import UDDataset # Make sure we can unpickle UDDataset mapping in this module.
|
| 29 |
+
import ufal.udpipe
|
| 30 |
+
|
| 31 |
+
__version__ = "1.0.0-dev"
|
| 32 |
+
|
| 33 |
+
|
| 34 |
+
class TooLongError(Exception):
|
| 35 |
+
pass
|
| 36 |
+
|
| 37 |
+
class Models:
|
| 38 |
+
class Model:
|
| 39 |
+
class Network:
|
| 40 |
+
_mutex = threading.Lock()
|
| 41 |
+
|
| 42 |
+
def __init__(self, path, server_args):
|
| 43 |
+
self._path = path
|
| 44 |
+
self._server_args = server_args
|
| 45 |
+
self.network, self.args, self.train = None, None, None
|
| 46 |
+
|
| 47 |
+
def load(self):
|
| 48 |
+
if self.network is not None:
|
| 49 |
+
return
|
| 50 |
+
with self._mutex:
|
| 51 |
+
if self.network is not None:
|
| 52 |
+
return
|
| 53 |
+
|
| 54 |
+
with open(os.path.join(self._path, "options.json"), mode="r") as options_file:
|
| 55 |
+
self.args = argparse.Namespace(**json.load(options_file))
|
| 56 |
+
self.args.batch_size = self._server_args.batch_size
|
| 57 |
+
self.args.load = [os.path.join(self._path, "model.weights.h5")]
|
| 58 |
+
self.train = latinpipe_evalatin24.UDDataset.from_mappings(os.path.join(self._path, "mappings.pkl"))
|
| 59 |
+
self.network = latinpipe_evalatin24.LatinPipeModel(self.train, self.args)
|
| 60 |
+
|
| 61 |
+
print("Loaded model {}".format(os.path.basename(self._path)), file=sys.stderr, flush=True)
|
| 62 |
+
|
| 63 |
+
|
| 64 |
+
def __init__(self, names, path, network, variant, acknowledgements, server_args):
|
| 65 |
+
self.names = names
|
| 66 |
+
self.acknowledgements = acknowledgements
|
| 67 |
+
self._network = network
|
| 68 |
+
self._variant = variant
|
| 69 |
+
self._server_args = server_args
|
| 70 |
+
|
| 71 |
+
# Load the tokenizer
|
| 72 |
+
tokenizer_path = os.path.join(path, "{}.tokenizer".format(variant))
|
| 73 |
+
self._tokenizer = ufal.udpipe.Model.load(tokenizer_path)
|
| 74 |
+
if self._tokenizer is None:
|
| 75 |
+
raise RuntimeError("Cannot load tokenizer from {}".format(tokenizer_path))
|
| 76 |
+
|
| 77 |
+
self._conllu_input = ufal.udpipe.InputFormat.newConlluInputFormat()
|
| 78 |
+
if self._conllu_input is None:
|
| 79 |
+
raise RuntimeError("Cannot create CoNLL-U input format")
|
| 80 |
+
|
| 81 |
+
self._conllu_output = ufal.udpipe.OutputFormat.newConlluOutputFormat()
|
| 82 |
+
if self._conllu_output is None:
|
| 83 |
+
raise RuntimeError("Cannot create CoNLL-U output format")
|
| 84 |
+
|
| 85 |
+
# Load the network if requested
|
| 86 |
+
if names[0] in server_args.preload_models or "all" in server_args.preload_models:
|
| 87 |
+
self._network.load()
|
| 88 |
+
|
| 89 |
+
def read(self, text, input_format):
|
| 90 |
+
reader = ufal.udpipe.InputFormat.newInputFormat(input_format)
|
| 91 |
+
if reader is None:
|
| 92 |
+
raise RuntimeError("Unknown input format '{}'".format(input_format))
|
| 93 |
+
# Do not return a generator, but a list to raise exceptions early
|
| 94 |
+
return list(self._read(text, reader))
|
| 95 |
+
|
| 96 |
+
def tokenize(self, text, tokenizer_options):
|
| 97 |
+
tokenizer = self._tokenizer.newTokenizer(tokenizer_options)
|
| 98 |
+
if tokenizer is None:
|
| 99 |
+
raise RuntimeError("Cannot create tokenizer.")
|
| 100 |
+
# Do not return a generator, but a list to raise exceptions early
|
| 101 |
+
return list(self._read(text, tokenizer))
|
| 102 |
+
|
| 103 |
+
def _read(self, text, reader):
|
| 104 |
+
sentence = ufal.udpipe.Sentence()
|
| 105 |
+
processing_error = ufal.udpipe.ProcessingError()
|
| 106 |
+
reader.setText(text)
|
| 107 |
+
while reader.nextSentence(sentence, processing_error):
|
| 108 |
+
if len(sentence.words) > 1001:
|
| 109 |
+
raise TooLongError()
|
| 110 |
+
yield sentence
|
| 111 |
+
sentence = ufal.udpipe.Sentence()
|
| 112 |
+
if processing_error.occurred():
|
| 113 |
+
raise RuntimeError("Cannot read input data: '{}'".format(processing_error.message))
|
| 114 |
+
|
| 115 |
+
def create_writer(self, output_format):
|
| 116 |
+
writer = ufal.udpipe.OutputFormat.newOutputFormat(output_format)
|
| 117 |
+
if writer is None:
|
| 118 |
+
raise RuntimeError("Unknown output format '{}'".format(output_format))
|
| 119 |
+
return writer
|
| 120 |
+
|
| 121 |
+
def predict(self, sentences, tag, parse, writer):
|
| 122 |
+
# Run the model
|
| 123 |
+
if tag or parse:
|
| 124 |
+
# Load the network if it has not been loaded already
|
| 125 |
+
self._network.load()
|
| 126 |
+
|
| 127 |
+
conllu_input = []
|
| 128 |
+
for sentence in sentences:
|
| 129 |
+
conllu_input.append(self._conllu_output.writeSentence(sentence))
|
| 130 |
+
|
| 131 |
+
time_ds = time.time()
|
| 132 |
+
# Create LatinPipe2Dataset
|
| 133 |
+
dataset = latinpipe_evalatin24.UDDataset(
|
| 134 |
+
"<web_input>", self._network.args, text="".join(conllu_input), train_dataset=self._network.train)
|
| 135 |
+
dataloader = latinpipe_evalatin24.TorchUDDataLoader(latinpipe_evalatin24.TorchUDDataset(
|
| 136 |
+
dataset, self._network.network.tokenizers, self._network.args, training=False), self._network.args)
|
| 137 |
+
|
| 138 |
+
# Prepare network arguments
|
| 139 |
+
current_args = argparse.Namespace(**vars(self._network.args))
|
| 140 |
+
if not tag: current_args.tags = []
|
| 141 |
+
if not parse: current_args.parse = 0
|
| 142 |
+
|
| 143 |
+
# Perform the prediction
|
| 144 |
+
time_nws = time.time()
|
| 145 |
+
with self._server_args.optional_semaphore:
|
| 146 |
+
time_nw = time.time()
|
| 147 |
+
predicted = self._network.network.predict(dataloader, args_override=current_args)
|
| 148 |
+
time_rd = time.time()
|
| 149 |
+
|
| 150 |
+
# Load the predicted CoNLL-U to ufal.udpipe sentences
|
| 151 |
+
sentences = self._read(predicted, self._conllu_input)
|
| 152 |
+
|
| 153 |
+
print("Request, DS {:.2f}ms,".format(1000 * (time_nws - time_ds)),
|
| 154 |
+
"NW {:.2f}+{:.2f}ms,".format(1000 * (time_rd - time_nw), 1000 * (time_nw - time_nws)),
|
| 155 |
+
"RD {:.2f}ms.".format(1000 * (time.time() - time_rd)),
|
| 156 |
+
file=sys.stderr, flush=True)
|
| 157 |
+
|
| 158 |
+
# Generate output
|
| 159 |
+
output = []
|
| 160 |
+
for sentence in sentences:
|
| 161 |
+
output.append(writer.writeSentence(sentence))
|
| 162 |
+
output.append(writer.finishDocument())
|
| 163 |
+
return "".join(output)
|
| 164 |
+
|
| 165 |
+
def __init__(self, server_args):
|
| 166 |
+
self.default_model = server_args.default_model
|
| 167 |
+
self.models_list = []
|
| 168 |
+
self.models_by_names = {}
|
| 169 |
+
networks_by_path = {}
|
| 170 |
+
|
| 171 |
+
for i in range(0, len(server_args.models), 4):
|
| 172 |
+
names, path, variant, acknowledgements = server_args.models[i:i+4]
|
| 173 |
+
names = names.split(":")
|
| 174 |
+
names = [name.split("-") for name in names]
|
| 175 |
+
names = ["-".join(parts[:None if not i else -i]) for parts in names for i in range(len(parts))]
|
| 176 |
+
|
| 177 |
+
if not path in networks_by_path:
|
| 178 |
+
networks_by_path[path] = self.Model.Network(path, server_args)
|
| 179 |
+
self.models_list.append(self.Model(names, path, networks_by_path[path], variant, acknowledgements, server_args))
|
| 180 |
+
for name in names:
|
| 181 |
+
self.models_by_names.setdefault(name, self.models_list[-1])
|
| 182 |
+
|
| 183 |
+
# Check the default model exists
|
| 184 |
+
assert self.default_model in self.models_by_names
|
| 185 |
+
|
| 186 |
+
|
| 187 |
+
class LatinPipeServer(socketserver.ThreadingTCPServer):
|
| 188 |
+
class LatinPipeServerRequestHandler(http.server.BaseHTTPRequestHandler):
|
| 189 |
+
protocol_version = "HTTP/1.1"
|
| 190 |
+
|
| 191 |
+
def respond(request, content_type, code=200, additional_headers={}):
|
| 192 |
+
request.close_connection = True
|
| 193 |
+
request.send_response(code)
|
| 194 |
+
request.send_header("Connection", "close")
|
| 195 |
+
request.send_header("Content-Type", content_type)
|
| 196 |
+
request.send_header("Access-Control-Allow-Origin", "*")
|
| 197 |
+
for key, value in additional_headers.items():
|
| 198 |
+
request.send_header(key, value)
|
| 199 |
+
request.end_headers()
|
| 200 |
+
|
| 201 |
+
def respond_error(request, message, code=400):
|
| 202 |
+
request.respond("text/plain", code)
|
| 203 |
+
request.wfile.write(message.encode("utf-8"))
|
| 204 |
+
|
| 205 |
+
def do_GET(request):
|
| 206 |
+
# Parse the URL
|
| 207 |
+
params = {}
|
| 208 |
+
try:
|
| 209 |
+
request.path = request.path.encode("iso-8859-1").decode("utf-8")
|
| 210 |
+
url = urllib.parse.urlparse(request.path)
|
| 211 |
+
for name, value in urllib.parse.parse_qsl(url.query, encoding="utf-8", keep_blank_values=True, errors="strict"):
|
| 212 |
+
params[name] = value
|
| 213 |
+
except:
|
| 214 |
+
return request.respond_error("Cannot parse request URL.")
|
| 215 |
+
|
| 216 |
+
# Parse the body of a POST request
|
| 217 |
+
if request.command == "POST":
|
| 218 |
+
if request.headers.get("Transfer-Encoding", "identity").lower() != "identity":
|
| 219 |
+
return request.respond_error("Only 'identity' Transfer-Encoding of payload is supported for now.")
|
| 220 |
+
|
| 221 |
+
try:
|
| 222 |
+
content_length = int(request.headers["Content-Length"])
|
| 223 |
+
except:
|
| 224 |
+
return request.respond_error("The Content-Length of payload is required.")
|
| 225 |
+
|
| 226 |
+
if content_length > request.server._server_args.max_request_size:
|
| 227 |
+
return request.respond_error("The payload size is too large.")
|
| 228 |
+
|
| 229 |
+
# Raw text on input for weblicht
|
| 230 |
+
if url.path.startswith("/weblicht/"):
|
| 231 |
+
# Ignore all but `model` GET param
|
| 232 |
+
params = {"model": params["model"]} if "model" in params else {}
|
| 233 |
+
|
| 234 |
+
try:
|
| 235 |
+
params["data"] = request.rfile.read(content_length).decode("utf-8")
|
| 236 |
+
except:
|
| 237 |
+
return request.respond_error("The payload is not in UTF-8 encoding.")
|
| 238 |
+
|
| 239 |
+
if url.path == "/weblicht/tokenize": params["tokenizer"] = ""
|
| 240 |
+
else: params["input"] = "conllu"
|
| 241 |
+
params["output"] = "conllu"
|
| 242 |
+
if url.path == "/weblicht/tag": params["tagger"] = ""
|
| 243 |
+
if url.path == "/weblicht/parse": params["parser"] = ""
|
| 244 |
+
# multipart/form-data
|
| 245 |
+
elif request.headers.get("Content-Type", "").startswith("multipart/form-data"):
|
| 246 |
+
try:
|
| 247 |
+
parser = email.parser.BytesFeedParser()
|
| 248 |
+
parser.feed(b"Content-Type: " + request.headers["Content-Type"].encode("ascii") + b"\r\n\r\n")
|
| 249 |
+
while content_length:
|
| 250 |
+
parser.feed(request.rfile.read(min(content_length, 4096)))
|
| 251 |
+
content_length -= min(content_length, 4096)
|
| 252 |
+
for part in parser.close().get_payload():
|
| 253 |
+
name = part.get_param("name", header="Content-Disposition")
|
| 254 |
+
if name:
|
| 255 |
+
params[name] = part.get_payload(decode=True).decode("utf-8")
|
| 256 |
+
except:
|
| 257 |
+
return request.respond_error("Cannot parse the multipart/form-data payload.")
|
| 258 |
+
# application/x-www-form-urlencoded
|
| 259 |
+
elif request.headers.get("Content-Type", "").startswith("application/x-www-form-urlencoded"):
|
| 260 |
+
try:
|
| 261 |
+
for name, value in urllib.parse.parse_qsl(
|
| 262 |
+
request.rfile.read(content_length).decode("utf-8"), encoding="utf-8", keep_blank_values=True, errors="strict"):
|
| 263 |
+
params[name] = value
|
| 264 |
+
except:
|
| 265 |
+
return request.respond_error("Cannot parse the application/x-www-form-urlencoded payload.")
|
| 266 |
+
else:
|
| 267 |
+
return request.respond_error("Unsupported payload Content-Type '{}'.".format(request.headers.get("Content-Type", "<none>")))
|
| 268 |
+
|
| 269 |
+
# Handle /models
|
| 270 |
+
if url.path == "/models":
|
| 271 |
+
response = {
|
| 272 |
+
"models": {model.names[0]: ["tokenizer", "tagger", "parser"] for model in request.server._models.models_list},
|
| 273 |
+
"default_model": request.server._models.default_model,
|
| 274 |
+
}
|
| 275 |
+
request.respond("application/json")
|
| 276 |
+
request.wfile.write(json.dumps(response, indent=1).encode("utf-8"))
|
| 277 |
+
# Handle /process
|
| 278 |
+
elif url.path in ["/process", "/weblicht/tokenize", "/weblicht/tag", "/weblicht/parse"]:
|
| 279 |
+
weblicht = url.path.startswith("/weblicht")
|
| 280 |
+
|
| 281 |
+
if "data" not in params:
|
| 282 |
+
return request.respond_error("The parameter 'data' is required.")
|
| 283 |
+
params["data"] = unicodedata.normalize("NFC", params["data"])
|
| 284 |
+
|
| 285 |
+
model = params.get("model", request.server._models.default_model)
|
| 286 |
+
if model not in request.server._models.models_by_names:
|
| 287 |
+
return request.respond_error("The requested model '{}' does not exist.".format(model))
|
| 288 |
+
model = request.server._models.models_by_names[model]
|
| 289 |
+
|
| 290 |
+
# Start by reading and optionally tokenizing the input data.
|
| 291 |
+
if "tokenizer" in params:
|
| 292 |
+
try:
|
| 293 |
+
sentences = model.tokenize(params["data"], params["tokenizer"])
|
| 294 |
+
except TooLongError:
|
| 295 |
+
return request.respond_error("During tokenization, sentence longer than 1000 words was found, aborting.\nThat should only happen with presegmented input.\nPlease make sure you do not generate such long sentences.\n")
|
| 296 |
+
except:
|
| 297 |
+
return request.respond_error("An error occured during tokenization of the input.")
|
| 298 |
+
else:
|
| 299 |
+
try:
|
| 300 |
+
sentences = model.read(params["data"], params.get("input", "conllu"))
|
| 301 |
+
except TooLongError:
|
| 302 |
+
return request.respond_error("Sentence longer than 1000 words was found on input, aborting.\nPlease make sure the input sentences have at most 1000 words.\n")
|
| 303 |
+
except:
|
| 304 |
+
return request.respond_error("Cannot parse the input in '{}' format.".format(params.get("input", "conllu")))
|
| 305 |
+
infclen = sum(sum(len(word.form) for word in sentence.words[1:]) for sentence in sentences)
|
| 306 |
+
|
| 307 |
+
# Create the writer
|
| 308 |
+
output_format = params.get("output", "conllu")
|
| 309 |
+
try:
|
| 310 |
+
writer = model.create_writer(output_format)
|
| 311 |
+
except:
|
| 312 |
+
return request.respond_error("Unknown output format '{}'.".format(output_format))
|
| 313 |
+
|
| 314 |
+
# Process the data
|
| 315 |
+
tag, parse, output_format = "tagger" in params, "parser" in params, params.get("output", "conllu")
|
| 316 |
+
batch, started_responding = [], False
|
| 317 |
+
try:
|
| 318 |
+
for sentence in itertools.chain(sentences, ["EOF"]):
|
| 319 |
+
if sentence == "EOF" or len(batch) == request.server._server_args.batch_size:
|
| 320 |
+
output = model.predict(batch, tag, parse, writer)
|
| 321 |
+
if not started_responding:
|
| 322 |
+
# The first batch is ready, we commit to generate output.
|
| 323 |
+
started_responding=True
|
| 324 |
+
if weblicht:
|
| 325 |
+
request.respond("application/conllu")
|
| 326 |
+
else:
|
| 327 |
+
request.respond("application/json", additional_headers={"X-Billing-Input-NFC-Len": str(infclen)})
|
| 328 |
+
request.wfile.write(json.dumps({
|
| 329 |
+
"model": model.names[0],
|
| 330 |
+
"acknowledgements": ["https://github.com/ufal/evalatin2024-latinpipe", model.acknowledgements],
|
| 331 |
+
"result": "",
|
| 332 |
+
}, indent=1)[:-3].encode("utf-8"))
|
| 333 |
+
if output_format == "conllu":
|
| 334 |
+
request.wfile.write(json.dumps(
|
| 335 |
+
"# generator = LatinPipe EvaLatin24, https://lindat.mff.cuni.cz/services/udpipe\n"
|
| 336 |
+
"# latinpipe_model = {}\n"
|
| 337 |
+
"# latinpipe_model_licence = CC BY-NC-SA\n".format(model.names[0]))[1:-1].encode("utf-8"))
|
| 338 |
+
if weblicht:
|
| 339 |
+
request.wfile.write(output.encode("utf-8"))
|
| 340 |
+
else:
|
| 341 |
+
request.wfile.write(json.dumps(output, ensure_ascii=False)[1:-1].encode("utf-8"))
|
| 342 |
+
batch = []
|
| 343 |
+
batch.append(sentence)
|
| 344 |
+
if not weblicht:
|
| 345 |
+
request.wfile.write(b'"\n}\n')
|
| 346 |
+
except:
|
| 347 |
+
import traceback
|
| 348 |
+
traceback.print_exc(file=sys.stderr)
|
| 349 |
+
sys.stderr.flush()
|
| 350 |
+
|
| 351 |
+
if not started_responding:
|
| 352 |
+
request.respond_error("An internal error occurred during processing.")
|
| 353 |
+
else:
|
| 354 |
+
if weblicht:
|
| 355 |
+
request.wfile.write(b'\n\nAn internal error occurred during processing, producing incorrect CoNLL-U!')
|
| 356 |
+
else:
|
| 357 |
+
request.wfile.write(b'",\n"An internal error occurred during processing, producing incorrect JSON!"')
|
| 358 |
+
# Unknown URL
|
| 359 |
+
else:
|
| 360 |
+
request.respond_error("No handler for the given URL '{}'".format(url.path), code=404)
|
| 361 |
+
|
| 362 |
+
def do_POST(request):
|
| 363 |
+
return request.do_GET()
|
| 364 |
+
|
| 365 |
+
daemon_threads = False
|
| 366 |
+
|
| 367 |
+
def __init__(self, server_args, models):
|
| 368 |
+
super().__init__(("", server_args.port), self.LatinPipeServerRequestHandler)
|
| 369 |
+
|
| 370 |
+
self._server_args = server_args
|
| 371 |
+
self._models = models
|
| 372 |
+
|
| 373 |
+
def server_bind(self):
|
| 374 |
+
import socket
|
| 375 |
+
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
| 376 |
+
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
|
| 377 |
+
super().server_bind()
|
| 378 |
+
|
| 379 |
+
def service_actions(self):
|
| 380 |
+
if isinstance(getattr(self, "_threads", None), list):
|
| 381 |
+
if len(self._threads) >= 1024:
|
| 382 |
+
self._threads = [thread for thread in self._threads if thread.is_alive()]
|
| 383 |
+
|
| 384 |
+
|
| 385 |
+
if __name__ == "__main__":
|
| 386 |
+
import signal
|
| 387 |
+
import threading
|
| 388 |
+
|
| 389 |
+
# Parse server arguments
|
| 390 |
+
parser = argparse.ArgumentParser()
|
| 391 |
+
parser.add_argument("port", type=int, help="Port to use")
|
| 392 |
+
parser.add_argument("default_model", type=str, help="Default model")
|
| 393 |
+
parser.add_argument("models", type=str, nargs="+", help="Models to serve")
|
| 394 |
+
parser.add_argument("--batch_size", default=32, type=int, help="Batch size")
|
| 395 |
+
parser.add_argument("--concurrent", default=None, type=int, help="Concurrent computations of NN")
|
| 396 |
+
parser.add_argument("--logfile", default=None, type=str, help="Log path")
|
| 397 |
+
parser.add_argument("--max_request_size", default=4096*1024, type=int, help="Maximum request size")
|
| 398 |
+
parser.add_argument("--preload_models", default=[], nargs="*", type=str, help="Models to preload, or `all`")
|
| 399 |
+
parser.add_argument("--threads", default=0, type=int, help="Threads to use")
|
| 400 |
+
args = parser.parse_args()
|
| 401 |
+
|
| 402 |
+
# Log stderr to logfile if given
|
| 403 |
+
if args.logfile is not None:
|
| 404 |
+
sys.stderr = open(args.logfile, "a", encoding="utf-8")
|
| 405 |
+
|
| 406 |
+
if args.threads:
|
| 407 |
+
# Limit the number of threads if requested
|
| 408 |
+
import torch
|
| 409 |
+
torch.set_num_threads(args.threads)
|
| 410 |
+
torch.set_num_interop_threads(args.threads)
|
| 411 |
+
|
| 412 |
+
# Load the models
|
| 413 |
+
models = Models(args)
|
| 414 |
+
|
| 415 |
+
# Create a semaphore if needed
|
| 416 |
+
args.optional_semaphore = threading.Semaphore(args.concurrent) if args.concurrent is not None else contextlib.nullcontext()
|
| 417 |
+
|
| 418 |
+
# Create the server
|
| 419 |
+
server = LatinPipeServer(args, models)
|
| 420 |
+
server_thread = threading.Thread(target=server.serve_forever, daemon=True)
|
| 421 |
+
server_thread.start()
|
| 422 |
+
|
| 423 |
+
print("Started LatinPipe server on port {}.".format(args.port), file=sys.stderr)
|
| 424 |
+
print("To stop it gracefully, either send SIGINT (Ctrl+C) or SIGUSR1.", file=sys.stderr, flush=True)
|
| 425 |
+
|
| 426 |
+
# Wait until the server should be closed
|
| 427 |
+
signal.pthread_sigmask(signal.SIG_BLOCK, [signal.SIGINT, signal.SIGUSR1])
|
| 428 |
+
signal.sigwait([signal.SIGINT, signal.SIGUSR1])
|
| 429 |
+
print("Initiating shutdown of the LatinPipe EvaLatin24 server.", file=sys.stderr, flush=True)
|
| 430 |
+
server.shutdown()
|
| 431 |
+
print("Stopped handling new requests, processing all current ones.", file=sys.stderr, flush=True)
|
| 432 |
+
server.server_close()
|
| 433 |
+
print("Finished shutdown of the LatinPipe EvaLatin24 server.", file=sys.stderr, flush=True)
|
src/evalatin2024-latinpipe/parsed.conllu
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# sent_id = S0001
|
| 2 |
+
# text = Uma frase como exemplo.
|
| 3 |
+
1 Uma um DET _ Definite=Ind|Gender=Fem|Number=Sing|PronType=Art 2 det _ _
|
| 4 |
+
2 frase frase NOUN _ Gender=Fem|Number=Sing 0 root _ _
|
| 5 |
+
3 como como ADP _ _ 4 case _ _
|
| 6 |
+
4 exemplo exemplo NOUN _ Gender=Masc|Number=Sing 2 nmod _ SpaceAfter=No
|
| 7 |
+
5 . . PUNCT _ _ 2 punct _ _
|
| 8 |
+
|
| 9 |
+
# sent_id = S0001
|
| 10 |
+
# text = O menino viu a menina com o telescópio.
|
| 11 |
+
1 O _ _ _ _ _ _ _ _
|
| 12 |
+
2 menino _ _ _ _ _ _ _ _
|
| 13 |
+
3 viu _ _ _ _ _ _ _ _
|
| 14 |
+
4 a _ _ _ _ _ _ _ _
|
| 15 |
+
5 menina _ _ _ _ _ _ _ _
|
| 16 |
+
6 com _ _ _ _ _ _ _ _
|
| 17 |
+
7 o _ _ _ _ _ _ _ _
|
| 18 |
+
8 telescópio _ _ _ _ _ _ _ SpaceAfter=No
|
| 19 |
+
9 . _ _ _ _ _ _ _ _
|
| 20 |
+
|
src/evalatin2024-latinpipe/requirements.txt
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
keras
|
| 2 |
+
torch
|
| 3 |
+
--extra-index-url=https://download.pytorch.org/whl/cu118
|
| 4 |
+
transformers
|
| 5 |
+
ufal.chu-liu-edmonds
|
| 6 |
+
|
| 7 |
+
# For latinpipe_evalatin24_server, you also need
|
| 8 |
+
# ufal.udpipe
|
src/img/c4ia.png
ADDED
|
src/img/icmc.png
ADDED
|
Git LFS Details
|
src/img/inova_nobackground.png
ADDED
|
src/img/mcti_nobackground.png
ADDED
|
src/img/motorola_nobackground.png
ADDED
|
src/img/nilc-removebg.png
ADDED
|
src/img/softex_nobackground.png
ADDED
|
src/img/wordcloud_brasil5.png
ADDED
|
Git LFS Details
|
src/portSentencer/abbrev.txt
ADDED
|
@@ -0,0 +1,397 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
dr.
|
| 2 |
+
dra.
|
| 3 |
+
sr.
|
| 4 |
+
sra.
|
| 5 |
+
prof.
|
| 6 |
+
profa.
|
| 7 |
+
Dr.
|
| 8 |
+
Dra.
|
| 9 |
+
Sr.
|
| 10 |
+
Sra.
|
| 11 |
+
Prof.
|
| 12 |
+
Profa.
|
| 13 |
+
DR.
|
| 14 |
+
DRA.
|
| 15 |
+
SR.
|
| 16 |
+
SRA.
|
| 17 |
+
PROF.
|
| 18 |
+
PROFA.
|
| 19 |
+
ilmo.
|
| 20 |
+
Ilmo.
|
| 21 |
+
ILMO.
|
| 22 |
+
bel.
|
| 23 |
+
Bel.
|
| 24 |
+
BEL.
|
| 25 |
+
eng.
|
| 26 |
+
Eng.
|
| 27 |
+
ENG.
|
| 28 |
+
reg.
|
| 29 |
+
Reg.
|
| 30 |
+
REG.
|
| 31 |
+
visc.
|
| 32 |
+
Visc.
|
| 33 |
+
VISC.
|
| 34 |
+
bar.
|
| 35 |
+
Bar.
|
| 36 |
+
BAR.
|
| 37 |
+
cond.
|
| 38 |
+
Cond.
|
| 39 |
+
COND.
|
| 40 |
+
séc.
|
| 41 |
+
Séc.
|
| 42 |
+
SÉC.
|
| 43 |
+
jr.
|
| 44 |
+
Jr.
|
| 45 |
+
JR.
|
| 46 |
+
ir.
|
| 47 |
+
Ir.
|
| 48 |
+
IR.
|
| 49 |
+
st.
|
| 50 |
+
St.
|
| 51 |
+
ST.
|
| 52 |
+
app.
|
| 53 |
+
App.
|
| 54 |
+
APP.
|
| 55 |
+
gov.
|
| 56 |
+
Gov.
|
| 57 |
+
GOV.
|
| 58 |
+
des.
|
| 59 |
+
Des.
|
| 60 |
+
DES.
|
| 61 |
+
gen.
|
| 62 |
+
Gen.
|
| 63 |
+
GEN.
|
| 64 |
+
gal.
|
| 65 |
+
Gal.
|
| 66 |
+
GAL.
|
| 67 |
+
cel.
|
| 68 |
+
Cel.
|
| 69 |
+
CEL.
|
| 70 |
+
col.
|
| 71 |
+
Col.
|
| 72 |
+
COL.
|
| 73 |
+
maj.
|
| 74 |
+
Maj.
|
| 75 |
+
MAJ.
|
| 76 |
+
ten.
|
| 77 |
+
Ten.
|
| 78 |
+
TEN.
|
| 79 |
+
cap.
|
| 80 |
+
Cap.
|
| 81 |
+
CAP.
|
| 82 |
+
capt.
|
| 83 |
+
Capt.
|
| 84 |
+
CAPT.
|
| 85 |
+
com.
|
| 86 |
+
Com.
|
| 87 |
+
COM.
|
| 88 |
+
brig.
|
| 89 |
+
Brig.
|
| 90 |
+
BRIG.
|
| 91 |
+
estac.
|
| 92 |
+
Estac.
|
| 93 |
+
ESTAC.
|
| 94 |
+
tel.
|
| 95 |
+
Tel.
|
| 96 |
+
TEL.
|
| 97 |
+
ave.
|
| 98 |
+
Ave.
|
| 99 |
+
AVE.
|
| 100 |
+
av.
|
| 101 |
+
Av.
|
| 102 |
+
AV.
|
| 103 |
+
trav.
|
| 104 |
+
Trav.
|
| 105 |
+
TRAV.
|
| 106 |
+
con.
|
| 107 |
+
Con.
|
| 108 |
+
CON.
|
| 109 |
+
jd.
|
| 110 |
+
Jd.
|
| 111 |
+
JD.
|
| 112 |
+
ed.
|
| 113 |
+
Ed.
|
| 114 |
+
ED.
|
| 115 |
+
lj.
|
| 116 |
+
Lj.
|
| 117 |
+
LJ.
|
| 118 |
+
cj.
|
| 119 |
+
Cj.
|
| 120 |
+
CJ.
|
| 121 |
+
apto.
|
| 122 |
+
Apto.
|
| 123 |
+
APTO.
|
| 124 |
+
apt.
|
| 125 |
+
Apt.
|
| 126 |
+
APT.
|
| 127 |
+
ingr.
|
| 128 |
+
Ingr.
|
| 129 |
+
INGR.
|
| 130 |
+
ap.
|
| 131 |
+
Ap.
|
| 132 |
+
AP.
|
| 133 |
+
dir.
|
| 134 |
+
Dir.
|
| 135 |
+
DIR.
|
| 136 |
+
min.
|
| 137 |
+
Min.
|
| 138 |
+
MIN.
|
| 139 |
+
sec.
|
| 140 |
+
Sec.
|
| 141 |
+
SEC.
|
| 142 |
+
kg.
|
| 143 |
+
Kg.
|
| 144 |
+
KG.
|
| 145 |
+
ml.
|
| 146 |
+
Ml.
|
| 147 |
+
ML.
|
| 148 |
+
km.
|
| 149 |
+
Km.
|
| 150 |
+
KM.
|
| 151 |
+
cm.
|
| 152 |
+
Cm.
|
| 153 |
+
CM.
|
| 154 |
+
vol.
|
| 155 |
+
Vol.
|
| 156 |
+
VOL.
|
| 157 |
+
PP.
|
| 158 |
+
pp.
|
| 159 |
+
Pp
|
| 160 |
+
pag.
|
| 161 |
+
Pag
|
| 162 |
+
PAG.
|
| 163 |
+
pág.
|
| 164 |
+
Pág
|
| 165 |
+
PÁG.
|
| 166 |
+
al.
|
| 167 |
+
Al.
|
| 168 |
+
AL.
|
| 169 |
+
etc.
|
| 170 |
+
i.e.
|
| 171 |
+
e.g.
|
| 172 |
+
cia.
|
| 173 |
+
Cia.
|
| 174 |
+
CIA.
|
| 175 |
+
co.
|
| 176 |
+
Co.
|
| 177 |
+
CO.
|
| 178 |
+
ltda.
|
| 179 |
+
Ltda.
|
| 180 |
+
LTDA.
|
| 181 |
+
ex.
|
| 182 |
+
Ex.
|
| 183 |
+
EX.
|
| 184 |
+
ac.
|
| 185 |
+
Ac.
|
| 186 |
+
AC.
|
| 187 |
+
dc.
|
| 188 |
+
Dc.
|
| 189 |
+
DC.
|
| 190 |
+
bros.
|
| 191 |
+
Bros.
|
| 192 |
+
BROS.
|
| 193 |
+
pq.
|
| 194 |
+
Pq.
|
| 195 |
+
PQ.
|
| 196 |
+
br.
|
| 197 |
+
Br.
|
| 198 |
+
BR.
|
| 199 |
+
cent.
|
| 200 |
+
Cent.
|
| 201 |
+
CENT.
|
| 202 |
+
ft.
|
| 203 |
+
Ft.
|
| 204 |
+
FT.
|
| 205 |
+
net.
|
| 206 |
+
Net.
|
| 207 |
+
NET.
|
| 208 |
+
no.
|
| 209 |
+
No.
|
| 210 |
+
NO.
|
| 211 |
+
nr.
|
| 212 |
+
Nr.
|
| 213 |
+
NR.
|
| 214 |
+
tr.
|
| 215 |
+
Tr.
|
| 216 |
+
TR.
|
| 217 |
+
mi.
|
| 218 |
+
Mi.
|
| 219 |
+
MI.
|
| 220 |
+
sta.
|
| 221 |
+
Sta.
|
| 222 |
+
STA.
|
| 223 |
+
sto.
|
| 224 |
+
Sto.
|
| 225 |
+
STO.
|
| 226 |
+
int.
|
| 227 |
+
Int.
|
| 228 |
+
INT.
|
| 229 |
+
inf.
|
| 230 |
+
Inf.
|
| 231 |
+
INF.
|
| 232 |
+
cult.
|
| 233 |
+
Cult.
|
| 234 |
+
CULT.
|
| 235 |
+
op.
|
| 236 |
+
Op.
|
| 237 |
+
OP.
|
| 238 |
+
aprox.
|
| 239 |
+
Aprox.
|
| 240 |
+
APROX.
|
| 241 |
+
it.
|
| 242 |
+
It.
|
| 243 |
+
IT.
|
| 244 |
+
ex.
|
| 245 |
+
Ex.
|
| 246 |
+
EX.
|
| 247 |
+
flex.
|
| 248 |
+
Flex.
|
| 249 |
+
FLEX.
|
| 250 |
+
ass.
|
| 251 |
+
Ass.
|
| 252 |
+
ASS.
|
| 253 |
+
pç.
|
| 254 |
+
Pç.
|
| 255 |
+
PÇ.
|
| 256 |
+
ind.
|
| 257 |
+
Ind.
|
| 258 |
+
IND.
|
| 259 |
+
vl.
|
| 260 |
+
Vl.
|
| 261 |
+
VL.
|
| 262 |
+
imp.
|
| 263 |
+
Imp.
|
| 264 |
+
IMP.
|
| 265 |
+
emp.
|
| 266 |
+
Emp.
|
| 267 |
+
EMP.
|
| 268 |
+
esq.
|
| 269 |
+
Esq.
|
| 270 |
+
ESQ.
|
| 271 |
+
dir.
|
| 272 |
+
Dir.
|
| 273 |
+
DIR.
|
| 274 |
+
ingr.
|
| 275 |
+
Ingr.
|
| 276 |
+
INGR.
|
| 277 |
+
pça.
|
| 278 |
+
Pça.
|
| 279 |
+
PÇA.
|
| 280 |
+
art.
|
| 281 |
+
Art.
|
| 282 |
+
ART.
|
| 283 |
+
sec.
|
| 284 |
+
Sec.
|
| 285 |
+
SEC.
|
| 286 |
+
a.
|
| 287 |
+
A.
|
| 288 |
+
b.
|
| 289 |
+
B.
|
| 290 |
+
c.
|
| 291 |
+
C.
|
| 292 |
+
d.
|
| 293 |
+
D.
|
| 294 |
+
e.
|
| 295 |
+
E.
|
| 296 |
+
f.
|
| 297 |
+
F.
|
| 298 |
+
g.
|
| 299 |
+
G.
|
| 300 |
+
h.
|
| 301 |
+
H.
|
| 302 |
+
i.
|
| 303 |
+
I.
|
| 304 |
+
j.
|
| 305 |
+
J.
|
| 306 |
+
k.
|
| 307 |
+
K.
|
| 308 |
+
l.
|
| 309 |
+
L.
|
| 310 |
+
m.
|
| 311 |
+
M.
|
| 312 |
+
n.
|
| 313 |
+
N.
|
| 314 |
+
o.
|
| 315 |
+
O.
|
| 316 |
+
p.
|
| 317 |
+
P.
|
| 318 |
+
q.
|
| 319 |
+
Q.
|
| 320 |
+
r.
|
| 321 |
+
R.
|
| 322 |
+
s.
|
| 323 |
+
S.
|
| 324 |
+
t.
|
| 325 |
+
T.
|
| 326 |
+
u.
|
| 327 |
+
U.
|
| 328 |
+
v.
|
| 329 |
+
V.
|
| 330 |
+
w.
|
| 331 |
+
W.
|
| 332 |
+
x.
|
| 333 |
+
X.
|
| 334 |
+
y.
|
| 335 |
+
Y.
|
| 336 |
+
z.
|
| 337 |
+
Z.
|
| 338 |
+
seg.
|
| 339 |
+
ter.
|
| 340 |
+
qua.
|
| 341 |
+
qui.
|
| 342 |
+
sex.
|
| 343 |
+
sab.
|
| 344 |
+
sáb.
|
| 345 |
+
dom.
|
| 346 |
+
Seg.
|
| 347 |
+
Ter.
|
| 348 |
+
Qua.
|
| 349 |
+
Qui.
|
| 350 |
+
Sex.
|
| 351 |
+
Sab.
|
| 352 |
+
Sáb.
|
| 353 |
+
Dom.
|
| 354 |
+
SEG.
|
| 355 |
+
TER.
|
| 356 |
+
QUA.
|
| 357 |
+
QUI.
|
| 358 |
+
SEX.
|
| 359 |
+
SAB.
|
| 360 |
+
SÁB.
|
| 361 |
+
DOM.
|
| 362 |
+
jan.
|
| 363 |
+
fev.
|
| 364 |
+
mar.
|
| 365 |
+
abr.
|
| 366 |
+
mai.
|
| 367 |
+
jun.
|
| 368 |
+
jul.
|
| 369 |
+
ago.
|
| 370 |
+
sep.
|
| 371 |
+
out.
|
| 372 |
+
nov.
|
| 373 |
+
dez.
|
| 374 |
+
Jan.
|
| 375 |
+
Fev.
|
| 376 |
+
Mar.
|
| 377 |
+
Abr.
|
| 378 |
+
Mai.
|
| 379 |
+
Jun.
|
| 380 |
+
Jul.
|
| 381 |
+
Ago.
|
| 382 |
+
Sep.
|
| 383 |
+
Out.
|
| 384 |
+
Nov.
|
| 385 |
+
Dez.
|
| 386 |
+
JAN.
|
| 387 |
+
FEV.
|
| 388 |
+
MAR.
|
| 389 |
+
ABR.
|
| 390 |
+
MAI.
|
| 391 |
+
JUN.
|
| 392 |
+
JUL.
|
| 393 |
+
AGO.
|
| 394 |
+
SET.
|
| 395 |
+
OUT.
|
| 396 |
+
NOV.
|
| 397 |
+
DEZ.
|
src/portSentencer/portSent.py
ADDED
|
@@ -0,0 +1,242 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# portSentencer - sentenciador de texto puro para o Portugues
|
| 2 |
+
#
|
| 3 |
+
# Este programa recebe diversos arquivos de entrada em formato
|
| 4 |
+
# textual e gera um arquivo textual com uma sentença por linha.
|
| 5 |
+
#
|
| 6 |
+
# Opções:
|
| 7 |
+
#
|
| 8 |
+
# -h help
|
| 9 |
+
# -o output file
|
| 10 |
+
# -r replace non standart characters
|
| 11 |
+
# -l limit the number of characters per sentence
|
| 12 |
+
#
|
| 13 |
+
# Exemplo de utilização:
|
| 14 |
+
#
|
| 15 |
+
# portSent -o sents.txt -r -l 2048 text1.txt text2.txt
|
| 16 |
+
#
|
| 17 |
+
# Busca o texto nos arquivos 'text1.txt' e 'text2.txt',
|
| 18 |
+
# substitui caracteres não usuais,
|
| 19 |
+
# gera sentenças com limite máximo de 2048 carateres e
|
| 20 |
+
# salva as sentenças no arquivo 'sents.txt'
|
| 21 |
+
#
|
| 22 |
+
# last edit: 01/21/2024
|
| 23 |
+
# created by Lucelene Lopes - [email protected]
|
| 24 |
+
|
| 25 |
+
import sys, os
|
| 26 |
+
|
| 27 |
+
#################################################
|
| 28 |
+
### Captura de argumentos da linha de comando
|
| 29 |
+
#################################################
|
| 30 |
+
def parseOptions(arguments):
|
| 31 |
+
# default options
|
| 32 |
+
output_file, input_files, replace, limit = "", [], False, 0
|
| 33 |
+
i = 1
|
| 34 |
+
while i < len(arguments):
|
| 35 |
+
if (arguments[i][0] == "-"):
|
| 36 |
+
# ajuda (help) - mostra ajuda, nada é executado
|
| 37 |
+
if ((arguments[i][1] == "h") and (len(arguments[i])==2)) or \
|
| 38 |
+
(arguments[i] == "-help"):
|
| 39 |
+
print("Opções:\n-h ajuda\n-o arquivo de saída", \
|
| 40 |
+
"-r substitui caracteres não padrão", \
|
| 41 |
+
"-l limite de caracteres por sentença", \
|
| 42 |
+
" -demais opções ignoradas, por favor execute novamente sem opção de ajuda",
|
| 43 |
+
"Exemplo de utilização:", \
|
| 44 |
+
"portSent -o sents.txt -r -l 2048 text1.txt text2.txt", \
|
| 45 |
+
"Busca o texto nos arquivos 'text1.txt' e 'text2.txt'", \
|
| 46 |
+
" substitui caracteres não usuais,", \
|
| 47 |
+
" gera sentenças com limite máximo de 2048 carateres e", \
|
| 48 |
+
" salva as sentenças no arquivo 'sents.txt'", \
|
| 49 |
+
sep="\n")
|
| 50 |
+
return None
|
| 51 |
+
# opção de substituição (replace) de caracteres não usuais
|
| 52 |
+
elif ((arguments[i][1] == "r") and (len(arguments[i])==2)) or \
|
| 53 |
+
(arguments[i] == "-replace"):
|
| 54 |
+
replace = True
|
| 55 |
+
i += 1
|
| 56 |
+
# opção de limite de tamanho de sentença (limit) - 0 para sem limite
|
| 57 |
+
elif ((arguments[i][1] == "l") and (len(arguments[i])==2)) or \
|
| 58 |
+
(arguments[i] == "-limit"):
|
| 59 |
+
try:
|
| 60 |
+
limit = eval(arguments[i+1])
|
| 61 |
+
i += 2
|
| 62 |
+
except:
|
| 63 |
+
print("limite de caracteres por sentença não informado - assumindo sem limite")
|
| 64 |
+
i += 1
|
| 65 |
+
# opção de arquivo de saída (um nome de arquivo)
|
| 66 |
+
elif ((arguments[i][1] == "o") and (len(arguments[i])==2)) or \
|
| 67 |
+
(arguments[i] == "-output"):
|
| 68 |
+
output_file = arguments[i+1]
|
| 69 |
+
i += 2
|
| 70 |
+
# opções inválidas - nada é executado
|
| 71 |
+
else:
|
| 72 |
+
print("Opção {} inválida, demais opções ignoradas, por favor execute novamente".format(arguments[i]))
|
| 73 |
+
return None
|
| 74 |
+
# arquivos de entrada (qualquer número) - só são incluídos se existirem
|
| 75 |
+
else:
|
| 76 |
+
if (os.path.isfile(arguments[i])):
|
| 77 |
+
input_files.append(arguments[i])
|
| 78 |
+
i += 1
|
| 79 |
+
else:
|
| 80 |
+
print("O arquivo {} não foi encontrado (ignorado)".format(arguments[i]))
|
| 81 |
+
i += 1
|
| 82 |
+
return [output_file, input_files, limit, replace]
|
| 83 |
+
|
| 84 |
+
#################################################
|
| 85 |
+
### função stripSents - faz de fato o sentenciamento
|
| 86 |
+
#################################################
|
| 87 |
+
def stripSents(inputText, outfile, limit, replace):
|
| 88 |
+
def cleanPrint(sent, outfile):
|
| 89 |
+
# do not print empty sentences
|
| 90 |
+
if (sent == "") or (sent == ".") or (sent == ".."):
|
| 91 |
+
return 0
|
| 92 |
+
# remove second . in sentences ending by ..
|
| 93 |
+
elif (len(sent) > 2) and (sent[-3:] != "...") and (sent[-2:] == ".."):
|
| 94 |
+
print(sent[:-1], file=outfile)
|
| 95 |
+
return 1
|
| 96 |
+
# insert . in sentences not ending by punctuation
|
| 97 |
+
elif (sent[-1] not in [".", "!", "?", ":", ";"]) and \
|
| 98 |
+
not ((sent[-1] in ["'", '"']) and (sent[-2] in [".", "!", "?"])):
|
| 99 |
+
print(sent+".", file=outfile)
|
| 100 |
+
return 1
|
| 101 |
+
# remove encompassing quotations " or ' if the quotations do not appear inside the sentence
|
| 102 |
+
elif (sent[0] == sent[1]) and ((sent[0] == "'") or (sent[0] == '"')) and (sent.count(sent[0]) == 2):
|
| 103 |
+
print(sent[1:-1], file=outfile)
|
| 104 |
+
return 1
|
| 105 |
+
# otherwise print it as it is
|
| 106 |
+
else:
|
| 107 |
+
print(sent, file=outfile)
|
| 108 |
+
return 1
|
| 109 |
+
def isAbbrev(chunk, abbrev):
|
| 110 |
+
abbr = False
|
| 111 |
+
for a in abbrev:
|
| 112 |
+
if (chunk == a):
|
| 113 |
+
abbr = True
|
| 114 |
+
break
|
| 115 |
+
else:
|
| 116 |
+
lasts = -len(a)
|
| 117 |
+
if (chunk[lasts:] == a) and (not chunk[lasts-1].isalpha()):
|
| 118 |
+
abbr = True
|
| 119 |
+
break
|
| 120 |
+
return abbr
|
| 121 |
+
# the function stripSents main body
|
| 122 |
+
abbrev = []
|
| 123 |
+
infile = open("./src/portSentencer/abbrev.txt", "r")
|
| 124 |
+
for line in infile:
|
| 125 |
+
abbrev.append(line[:-1])
|
| 126 |
+
infile.close()
|
| 127 |
+
if (replace):
|
| 128 |
+
replaceables = [[" ", " "], \
|
| 129 |
+
["—", "-"], ["–", "-"], \
|
| 130 |
+
['"', '"'], \
|
| 131 |
+
['“', '"'], ['”', '"'], \
|
| 132 |
+
['‟', '"'], ['″', '"'], \
|
| 133 |
+
['‶', '"'], ['〃', '"'], \
|
| 134 |
+
['״', '"'], ['˝', '"'], \
|
| 135 |
+
['ʺ', '"'], ['˶', '"'], \
|
| 136 |
+
['ˮ', '"'], ['ײ', '"'], \
|
| 137 |
+
[" ‣", "."], [" >>", "."], [" ○", "."], [" *", "."], \
|
| 138 |
+
[" | ", ". "], [" .", "."], \
|
| 139 |
+
["\n", " "], ["\t", " "]]
|
| 140 |
+
else:
|
| 141 |
+
replaceables = [["\n", " "], ["\t", " "]]
|
| 142 |
+
tmp = inputText.replace(" "," ")
|
| 143 |
+
for r in replaceables:
|
| 144 |
+
tmp = tmp.replace(r[0], r[1])
|
| 145 |
+
while (tmp.find(" ") != -1):
|
| 146 |
+
tmp = tmp.replace(" "," ")
|
| 147 |
+
if (tmp[0] == " "):
|
| 148 |
+
tmp = tmp[1:]
|
| 149 |
+
bagOfChunks = tmp.split(" ")
|
| 150 |
+
s, sent = 0, ""
|
| 151 |
+
if (bagOfChunks[-1] == ""):
|
| 152 |
+
bagOfChunks.pop()
|
| 153 |
+
for i in range(len(bagOfChunks)):
|
| 154 |
+
# if it is the last chunk, it is the end of sentence
|
| 155 |
+
if (i == len(bagOfChunks)-1):
|
| 156 |
+
sent += " " + bagOfChunks[i]
|
| 157 |
+
s += cleanPrint(sent[1:], outfile)
|
| 158 |
+
break
|
| 159 |
+
chunk = bagOfChunks[i]
|
| 160 |
+
# if there is a limit and the chunk is greater than the limit, discard it
|
| 161 |
+
if (limit != 0) and (len(chunk) > limit):
|
| 162 |
+
continue
|
| 163 |
+
# if there is a limit and it is reached, ends the sentence arbitrarily
|
| 164 |
+
elif (limit != 0) and (len(sent) + len(chunk) > limit):
|
| 165 |
+
s += cleanPrint(sent[1:], outfile)
|
| 166 |
+
sent = chunk
|
| 167 |
+
# if the chunk is too short
|
| 168 |
+
elif (len(chunk) < 3) and (len(chunk) != 0):
|
| 169 |
+
sent += " " + chunk
|
| 170 |
+
# if the chunk is empty
|
| 171 |
+
elif (len(chunk) == 0):
|
| 172 |
+
continue
|
| 173 |
+
# ! ? or ... always mark an end of sentence
|
| 174 |
+
elif (chunk[-3:] == "...") or (chunk[-1] == "!") or (chunk[-1] == "?"):
|
| 175 |
+
sent += " " + chunk
|
| 176 |
+
s += cleanPrint(sent[1:], outfile)
|
| 177 |
+
sent = ""
|
| 178 |
+
# a . : or ; followed by a lowercase chunk is not an end of sentence
|
| 179 |
+
elif ((chunk[-1] == ".") or (chunk[-1] == ":") or (chunk[-1] == ";")) and (bagOfChunks[i+1][0].islower()):
|
| 180 |
+
sent += " " + chunk
|
| 181 |
+
# a : or ; not followed by a lowercase chunk is an end of sentence
|
| 182 |
+
elif ((chunk[-1] == ":") or (chunk[-1] == ";")) and (not bagOfChunks[i+1][0].islower()):
|
| 183 |
+
sent += " " + chunk
|
| 184 |
+
s += cleanPrint(sent[1:], outfile)
|
| 185 |
+
sent = ""
|
| 186 |
+
# chunk ends with ! or ? followed by quotations that had appear before an odd number is an end of sentence
|
| 187 |
+
elif (chunk[-2:] in ["!'", '!"', "?'", '?"']):
|
| 188 |
+
sent += " " + chunk
|
| 189 |
+
s += cleanPrint(sent[1:], outfile)
|
| 190 |
+
sent = ""
|
| 191 |
+
elif (chunk[-2:] in [".'", '."']):
|
| 192 |
+
sent += " " + chunk
|
| 193 |
+
abbr = isAbbrev(chunk[:-1], abbrev)
|
| 194 |
+
if not abbr:
|
| 195 |
+
s += cleanPrint(sent[1:], outfile)
|
| 196 |
+
sent = ""
|
| 197 |
+
# a chunk not ending with ! ? ... ; : or . is not an end of sentence
|
| 198 |
+
elif (chunk[-1] != "."):
|
| 199 |
+
sent += " " + chunk
|
| 200 |
+
# chunk ending by . is either a know abbreviation (not an end of sentence), or an end of sentence
|
| 201 |
+
elif (chunk[-1] == "."):
|
| 202 |
+
abbr = isAbbrev(chunk, abbrev)
|
| 203 |
+
if (abbr):
|
| 204 |
+
sent += " " + chunk
|
| 205 |
+
else:
|
| 206 |
+
sent += " " + chunk
|
| 207 |
+
s += cleanPrint(sent[1:], outfile)
|
| 208 |
+
sent = ""
|
| 209 |
+
# return the number of generated sentences
|
| 210 |
+
return s
|
| 211 |
+
|
| 212 |
+
#################################################
|
| 213 |
+
### função principal do programa - busca argumentos e chama 'stripSents' que faz de fato o sentenciamento
|
| 214 |
+
#################################################
|
| 215 |
+
def portSent():
|
| 216 |
+
if (len(sys.argv) == 1):
|
| 217 |
+
arguments = ["sents2.txt", ["relic.txt"], 0, True]
|
| 218 |
+
print("Assumindo default: 'sents.txt' como arquivo de saída, 'text1.txt' como arquivo de entrada, sem limite e substituições.")
|
| 219 |
+
else:
|
| 220 |
+
arguments = parseOptions(sys.argv)
|
| 221 |
+
if (arguments != None):
|
| 222 |
+
if (arguments[0] == ""):
|
| 223 |
+
print("Assumindo 'sents.txt' como arquivo de saída")
|
| 224 |
+
arguments[0] = 'sents.txt'
|
| 225 |
+
if (arguments[1] == []):
|
| 226 |
+
print("Nenhum arquivo de entrada válido - por favor corrija e tente novamente")
|
| 227 |
+
else:
|
| 228 |
+
outfile = open(arguments[0], "w")
|
| 229 |
+
inputText = ""
|
| 230 |
+
for oneInput in arguments[1]:
|
| 231 |
+
infile = open(oneInput, "r")
|
| 232 |
+
inputText += infile.read()
|
| 233 |
+
infile.close()
|
| 234 |
+
s = stripSents(inputText, outfile, arguments[2], arguments[3])
|
| 235 |
+
outfile.close()
|
| 236 |
+
print("Sentenciamento terminado com {} sentenças extraídas e salvas em {}".format(s, arguments[0]))
|
| 237 |
+
else:
|
| 238 |
+
print("Problemas com parâmetros - por favor corrija e tente novamente")
|
| 239 |
+
|
| 240 |
+
portSent()
|
| 241 |
+
|
| 242 |
+
|
src/portTokenizer/ADJ.tsv
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
src/portTokenizer/ADP.tsv
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
a a _
|
| 2 |
+
afora afora _
|
| 3 |
+
ante ante _
|
| 4 |
+
após após _
|
| 5 |
+
até até _
|
| 6 |
+
com com _
|
| 7 |
+
como como _
|
| 8 |
+
conforme conforme _
|
| 9 |
+
consoante consoante _
|
| 10 |
+
contra contra _
|
| 11 |
+
dado dado _
|
| 12 |
+
de de _
|
| 13 |
+
desde desde _
|
| 14 |
+
devido devido _
|
| 15 |
+
durante durante _
|
| 16 |
+
em em _
|
| 17 |
+
entre entre _
|
| 18 |
+
exceto exceto _
|
| 19 |
+
fora fora _
|
| 20 |
+
malgrado malgrado _
|
| 21 |
+
mediante mediante _
|
| 22 |
+
menos menos _
|
| 23 |
+
para para _
|
| 24 |
+
perante perante _
|
| 25 |
+
por por _
|
| 26 |
+
pra para Abbr=Yes
|
| 27 |
+
pró pró _
|
| 28 |
+
que que _
|
| 29 |
+
salvo salvo _
|
| 30 |
+
segundo segundo _
|
| 31 |
+
sem sem _
|
| 32 |
+
senão senão _
|
| 33 |
+
sob sob _
|
| 34 |
+
sobre sobre _
|
| 35 |
+
versus versus _
|
| 36 |
+
via via _
|
| 37 |
+
visto visto _
|
| 38 |
+
vs versus Abbr=Yes
|
src/portTokenizer/ADV.tsv
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
src/portTokenizer/AUX.tsv
ADDED
|
@@ -0,0 +1,435 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
era ser Mood=Ind|Number=Sing|Person=1|Tense=Imp|VerbForm=Fin
|
| 2 |
+
era ser Mood=Ind|Number=Sing|Person=3|Tense=Imp|VerbForm=Fin
|
| 3 |
+
eram ser Mood=Ind|Number=Plur|Person=3|Tense=Imp|VerbForm=Fin
|
| 4 |
+
eras ser Mood=Ind|Number=Sing|Person=2|Tense=Imp|VerbForm=Fin
|
| 5 |
+
estada estar Gender=Fem|Number=Sing|VerbForm=Part
|
| 6 |
+
estadas estar Gender=Fem|Number=Plur|VerbForm=Part
|
| 7 |
+
estado estar Gender=Masc|Number=Sing|VerbForm=Part
|
| 8 |
+
estados estar Gender=Masc|Number=Plur|VerbForm=Part
|
| 9 |
+
estai estar Mood=Imp|Number=Plur|Person=2|VerbForm=Fin
|
| 10 |
+
estais estar Mood=Ind|Number=Plur|Person=2|Tense=Pres|VerbForm=Fin
|
| 11 |
+
estamos estar Mood=Ind|Number=Plur|Person=1|Tense=Pres|VerbForm=Fin
|
| 12 |
+
estando estar VerbForm=Ger
|
| 13 |
+
estar estar Number=Sing|Person=1|VerbForm=Inf
|
| 14 |
+
estar estar Number=Sing|Person=3|VerbForm=Inf
|
| 15 |
+
estar estar VerbForm=Inf
|
| 16 |
+
estardes estar Number=Plur|Person=2|VerbForm=Inf
|
| 17 |
+
estarei estar Mood=Ind|Number=Sing|Person=1|Tense=Fut|VerbForm=Fin
|
| 18 |
+
estareis estar Mood=Ind|Number=Plur|Person=2|Tense=Fut|VerbForm=Fin
|
| 19 |
+
estarem estar Number=Plur|Person=3|VerbForm=Inf
|
| 20 |
+
estaremos estar Mood=Ind|Number=Plur|Person=1|Tense=Fut|VerbForm=Fin
|
| 21 |
+
estares estar Number=Sing|Person=2|VerbForm=Inf
|
| 22 |
+
estaria estar Mood=Cnd|Number=Sing|Person=1|VerbForm=Fin
|
| 23 |
+
estaria estar Mood=Cnd|Number=Sing|Person=3|VerbForm=Fin
|
| 24 |
+
estariam estar Mood=Cnd|Number=Plur|Person=3|VerbForm=Fin
|
| 25 |
+
estarias estar Mood=Cnd|Number=Sing|Person=2|VerbForm=Fin
|
| 26 |
+
estarmos estar Number=Plur|Person=1|VerbForm=Inf
|
| 27 |
+
estará estar Mood=Ind|Number=Sing|Person=3|Tense=Fut|VerbForm=Fin
|
| 28 |
+
estarás estar Mood=Ind|Number=Sing|Person=2|Tense=Fut|VerbForm=Fin
|
| 29 |
+
estarão estar Mood=Ind|Number=Plur|Person=3|Tense=Fut|VerbForm=Fin
|
| 30 |
+
estaríamos estar Mood=Cnd|Number=Plur|Person=1|VerbForm=Fin
|
| 31 |
+
estaríeis estar Mood=Cnd|Number=Plur|Person=2|VerbForm=Fin
|
| 32 |
+
estava estar Mood=Ind|Number=Sing|Person=1|Tense=Imp|VerbForm=Fin
|
| 33 |
+
estava estar Mood=Ind|Number=Sing|Person=3|Tense=Imp|VerbForm=Fin
|
| 34 |
+
estavam estar Mood=Ind|Number=Plur|Person=3|Tense=Imp|VerbForm=Fin
|
| 35 |
+
estavas estar Mood=Ind|Number=Sing|Person=2|Tense=Imp|VerbForm=Fin
|
| 36 |
+
esteja estar Mood=Imp|Number=Sing|Person=3|VerbForm=Fin
|
| 37 |
+
esteja estar Mood=Sub|Number=Sing|Person=1|Tense=Pres|VerbForm=Fin
|
| 38 |
+
esteja estar Mood=Sub|Number=Sing|Person=3|Tense=Pres|VerbForm=Fin
|
| 39 |
+
estejais estar Mood=Sub|Number=Plur|Person=2|Tense=Pres|VerbForm=Fin
|
| 40 |
+
estejam estar Mood=Imp|Number=Plur|Person=3|VerbForm=Fin
|
| 41 |
+
estejam estar Mood=Sub|Number=Plur|Person=3|Tense=Pres|VerbForm=Fin
|
| 42 |
+
estejamos estar Mood=Imp|Number=Plur|Person=1|VerbForm=Fin
|
| 43 |
+
estejamos estar Mood=Sub|Number=Plur|Person=1|Tense=Pres|VerbForm=Fin
|
| 44 |
+
estejas estar Mood=Sub|Number=Sing|Person=2|Tense=Pres|VerbForm=Fin
|
| 45 |
+
esteve estar Mood=Ind|Number=Sing|Person=3|Tense=Past|VerbForm=Fin
|
| 46 |
+
estive estar Mood=Ind|Number=Sing|Person=1|Tense=Past|VerbForm=Fin
|
| 47 |
+
estivemos estar Mood=Ind|Number=Plur|Person=1|Tense=Past|VerbForm=Fin
|
| 48 |
+
estiver estar Mood=Sub|Number=Sing|Person=1|Tense=Fut|VerbForm=Fin
|
| 49 |
+
estiver estar Mood=Sub|Number=Sing|Person=3|Tense=Fut|VerbForm=Fin
|
| 50 |
+
estivera estar Mood=Ind|Number=Sing|Person=1|Tense=Pqp|VerbForm=Fin
|
| 51 |
+
estivera estar Mood=Ind|Number=Sing|Person=3|Tense=Pqp|VerbForm=Fin
|
| 52 |
+
estiveram estar Mood=Ind|Number=Plur|Person=3|Tense=Past|VerbForm=Fin
|
| 53 |
+
estiveram estar Mood=Ind|Number=Plur|Person=3|Tense=Pqp|VerbForm=Fin
|
| 54 |
+
estiveras estar Mood=Ind|Number=Sing|Person=2|Tense=Pqp|VerbForm=Fin
|
| 55 |
+
estiverdes estar Mood=Sub|Number=Plur|Person=2|Tense=Fut|VerbForm=Fin
|
| 56 |
+
estiverem estar Mood=Sub|Number=Plur|Person=3|Tense=Fut|VerbForm=Fin
|
| 57 |
+
estiveres estar Mood=Sub|Number=Sing|Person=2|Tense=Fut|VerbForm=Fin
|
| 58 |
+
estivermos estar Mood=Sub|Number=Plur|Person=1|Tense=Fut|VerbForm=Fin
|
| 59 |
+
estivesse estar Mood=Sub|Number=Sing|Person=1|Tense=Past|VerbForm=Fin
|
| 60 |
+
estivesse estar Mood=Sub|Number=Sing|Person=3|Tense=Past|VerbForm=Fin
|
| 61 |
+
estivessem estar Mood=Sub|Number=Plur|Person=3|Tense=Past|VerbForm=Fin
|
| 62 |
+
estivesses estar Mood=Sub|Number=Sing|Person=2|Tense=Past|VerbForm=Fin
|
| 63 |
+
estiveste estar Mood=Ind|Number=Sing|Person=2|Tense=Past|VerbForm=Fin
|
| 64 |
+
estivestes estar Mood=Ind|Number=Plur|Person=2|Tense=Past|VerbForm=Fin
|
| 65 |
+
estivéramos estar Mood=Ind|Number=Plur|Person=1|Tense=Pqp|VerbForm=Fin
|
| 66 |
+
estivéreis estar Mood=Ind|Number=Plur|Person=2|Tense=Pqp|VerbForm=Fin
|
| 67 |
+
estivésseis estar Mood=Sub|Number=Plur|Person=2|Tense=Past|VerbForm=Fin
|
| 68 |
+
estivéssemos estar Mood=Sub|Number=Plur|Person=1|Tense=Past|VerbForm=Fin
|
| 69 |
+
estou estar Mood=Ind|Number=Sing|Person=1|Tense=Pres|VerbForm=Fin
|
| 70 |
+
está estar Mood=Imp|Number=Sing|Person=2|VerbForm=Fin
|
| 71 |
+
está estar Mood=Ind|Number=Sing|Person=3|Tense=Pres|VerbForm=Fin
|
| 72 |
+
estás estar Mood=Ind|Number=Sing|Person=2|Tense=Pres|VerbForm=Fin
|
| 73 |
+
estávamos estar Mood=Ind|Number=Plur|Person=1|Tense=Imp|VerbForm=Fin
|
| 74 |
+
estáveis estar Mood=Ind|Number=Plur|Person=2|Tense=Imp|VerbForm=Fin
|
| 75 |
+
estão estar Mood=Ind|Number=Plur|Person=3|Tense=Pres|VerbForm=Fin
|
| 76 |
+
foi ir Mood=Ind|Number=Sing|Person=3|Tense=Past|VerbForm=Fin
|
| 77 |
+
foi ser Mood=Ind|Number=Sing|Person=3|Tense=Past|VerbForm=Fin
|
| 78 |
+
fomos ir Mood=Ind|Number=Plur|Person=1|Tense=Past|VerbForm=Fin
|
| 79 |
+
fomos ser Mood=Ind|Number=Plur|Person=1|Tense=Past|VerbForm=Fin
|
| 80 |
+
for ir Mood=Sub|Number=Sing|Person=1|Tense=Fut|VerbForm=Fin
|
| 81 |
+
for ir Mood=Sub|Number=Sing|Person=3|Tense=Fut|VerbForm=Fin
|
| 82 |
+
for ser Mood=Sub|Number=Sing|Person=1|Tense=Fut|VerbForm=Fin
|
| 83 |
+
for ser Mood=Sub|Number=Sing|Person=3|Tense=Fut|VerbForm=Fin
|
| 84 |
+
fora ir Mood=Ind|Number=Sing|Person=1|Tense=Pqp|VerbForm=Fin
|
| 85 |
+
fora ir Mood=Ind|Number=Sing|Person=3|Tense=Pqp|VerbForm=Fin
|
| 86 |
+
fora ser Mood=Ind|Number=Sing|Person=1|Tense=Pqp|VerbForm=Fin
|
| 87 |
+
fora ser Mood=Ind|Number=Sing|Person=3|Tense=Pqp|VerbForm=Fin
|
| 88 |
+
foram ir Mood=Ind|Number=Plur|Person=3|Tense=Past|VerbForm=Fin
|
| 89 |
+
foram ir Mood=Ind|Number=Plur|Person=3|Tense=Pqp|VerbForm=Fin
|
| 90 |
+
foram ser Mood=Ind|Number=Plur|Person=3|Tense=Past|VerbForm=Fin
|
| 91 |
+
foram ser Mood=Ind|Number=Plur|Person=3|Tense=Pqp|VerbForm=Fin
|
| 92 |
+
foras ir Mood=Ind|Number=Sing|Person=2|Tense=Pqp|VerbForm=Fin
|
| 93 |
+
foras ser Mood=Ind|Number=Sing|Person=2|Tense=Pqp|VerbForm=Fin
|
| 94 |
+
fordes ir Mood=Sub|Number=Plur|Person=2|Tense=Fut|VerbForm=Fin
|
| 95 |
+
fordes ser Mood=Sub|Number=Plur|Person=2|Tense=Fut|VerbForm=Fin
|
| 96 |
+
forem ir Mood=Sub|Number=Plur|Person=3|Tense=Fut|VerbForm=Fin
|
| 97 |
+
forem ser Mood=Sub|Number=Plur|Person=3|Tense=Fut|VerbForm=Fin
|
| 98 |
+
fores ir Mood=Sub|Number=Sing|Person=2|Tense=Fut|VerbForm=Fin
|
| 99 |
+
fores ser Mood=Sub|Number=Sing|Person=2|Tense=Fut|VerbForm=Fin
|
| 100 |
+
formos ir Mood=Sub|Number=Plur|Person=1|Tense=Fut|VerbForm=Fin
|
| 101 |
+
formos ser Mood=Sub|Number=Plur|Person=1|Tense=Fut|VerbForm=Fin
|
| 102 |
+
fosse ir Mood=Sub|Number=Sing|Person=1|Tense=Past|VerbForm=Fin
|
| 103 |
+
fosse ir Mood=Sub|Number=Sing|Person=3|Tense=Past|VerbForm=Fin
|
| 104 |
+
fosse ser Mood=Sub|Number=Sing|Person=1|Tense=Past|VerbForm=Fin
|
| 105 |
+
fosse ser Mood=Sub|Number=Sing|Person=3|Tense=Past|VerbForm=Fin
|
| 106 |
+
fossem ir Mood=Sub|Number=Plur|Person=3|Tense=Past|VerbForm=Fin
|
| 107 |
+
fossem ser Mood=Sub|Number=Plur|Person=3|Tense=Past|VerbForm=Fin
|
| 108 |
+
fosses ir Mood=Sub|Number=Sing|Person=2|Tense=Past|VerbForm=Fin
|
| 109 |
+
fosses ser Mood=Sub|Number=Sing|Person=2|Tense=Past|VerbForm=Fin
|
| 110 |
+
foste ir Mood=Ind|Number=Sing|Person=2|Tense=Past|VerbForm=Fin
|
| 111 |
+
foste ser Mood=Ind|Number=Sing|Person=2|Tense=Past|VerbForm=Fin
|
| 112 |
+
fostes ir Mood=Ind|Number=Plur|Person=2|Tense=Past|VerbForm=Fin
|
| 113 |
+
fostes ser Mood=Ind|Number=Plur|Person=2|Tense=Past|VerbForm=Fin
|
| 114 |
+
fui ir Mood=Ind|Number=Sing|Person=1|Tense=Past|VerbForm=Fin
|
| 115 |
+
fui ser Mood=Ind|Number=Sing|Person=1|Tense=Past|VerbForm=Fin
|
| 116 |
+
fôramos ir Mood=Ind|Number=Plur|Person=1|Tense=Pqp|VerbForm=Fin
|
| 117 |
+
fôramos ser Mood=Ind|Number=Plur|Person=1|Tense=Pqp|VerbForm=Fin
|
| 118 |
+
fôreis ir Mood=Ind|Number=Plur|Person=2|Tense=Pqp|VerbForm=Fin
|
| 119 |
+
fôreis ser Mood=Ind|Number=Plur|Person=2|Tense=Pqp|VerbForm=Fin
|
| 120 |
+
fôsseis ir Mood=Sub|Number=Plur|Person=2|Tense=Past|VerbForm=Fin
|
| 121 |
+
fôsseis ser Mood=Sub|Number=Plur|Person=2|Tense=Past|VerbForm=Fin
|
| 122 |
+
fôssemos ir Mood=Sub|Number=Plur|Person=1|Tense=Past|VerbForm=Fin
|
| 123 |
+
fôssemos ser Mood=Sub|Number=Plur|Person=1|Tense=Past|VerbForm=Fin
|
| 124 |
+
haja haver Mood=Imp|Number=Sing|Person=3|VerbForm=Fin
|
| 125 |
+
haja haver Mood=Sub|Number=Sing|Person=1|Tense=Pres|VerbForm=Fin
|
| 126 |
+
haja haver Mood=Sub|Number=Sing|Person=3|Tense=Pres|VerbForm=Fin
|
| 127 |
+
hajais haver Mood=Sub|Number=Plur|Person=2|Tense=Pres|VerbForm=Fin
|
| 128 |
+
hajam haver Mood=Imp|Number=Plur|Person=3|VerbForm=Fin
|
| 129 |
+
hajam haver Mood=Sub|Number=Plur|Person=3|Tense=Pres|VerbForm=Fin
|
| 130 |
+
hajamos haver Mood=Imp|Number=Plur|Person=1|VerbForm=Fin
|
| 131 |
+
hajamos haver Mood=Sub|Number=Plur|Person=1|Tense=Pres|VerbForm=Fin
|
| 132 |
+
hajas haver Mood=Sub|Number=Sing|Person=2|Tense=Pres|VerbForm=Fin
|
| 133 |
+
havei haver Mood=Imp|Number=Plur|Person=2|VerbForm=Fin
|
| 134 |
+
haveis haver Mood=Ind|Number=Plur|Person=2|Tense=Pres|VerbForm=Fin
|
| 135 |
+
havemos haver Mood=Ind|Number=Plur|Person=1|Tense=Pres|VerbForm=Fin
|
| 136 |
+
havendo haver VerbForm=Ger
|
| 137 |
+
haver haver Number=Sing|Person=1|VerbForm=Inf
|
| 138 |
+
haver haver Number=Sing|Person=3|VerbForm=Inf
|
| 139 |
+
haver haver VerbForm=Inf
|
| 140 |
+
haverdes haver Number=Plur|Person=2|VerbForm=Inf
|
| 141 |
+
haverei haver Mood=Ind|Number=Sing|Person=1|Tense=Fut|VerbForm=Fin
|
| 142 |
+
havereis haver Mood=Ind|Number=Plur|Person=2|Tense=Fut|VerbForm=Fin
|
| 143 |
+
haverem haver Number=Plur|Person=3|VerbForm=Inf
|
| 144 |
+
haveremos haver Mood=Ind|Number=Plur|Person=1|Tense=Fut|VerbForm=Fin
|
| 145 |
+
haveres haver Number=Sing|Person=2|VerbForm=Inf
|
| 146 |
+
haveria haver Mood=Cnd|Number=Sing|Person=1|VerbForm=Fin
|
| 147 |
+
haveria haver Mood=Cnd|Number=Sing|Person=3|VerbForm=Fin
|
| 148 |
+
haveriam haver Mood=Cnd|Number=Plur|Person=3|VerbForm=Fin
|
| 149 |
+
haverias haver Mood=Cnd|Number=Sing|Person=2|VerbForm=Fin
|
| 150 |
+
havermos haver Number=Plur|Person=1|VerbForm=Inf
|
| 151 |
+
haverá haver Mood=Ind|Number=Sing|Person=3|Tense=Fut|VerbForm=Fin
|
| 152 |
+
haverás haver Mood=Ind|Number=Sing|Person=2|Tense=Fut|VerbForm=Fin
|
| 153 |
+
haverão haver Mood=Ind|Number=Plur|Person=3|Tense=Fut|VerbForm=Fin
|
| 154 |
+
haveríamos haver Mood=Cnd|Number=Plur|Person=1|VerbForm=Fin
|
| 155 |
+
haveríeis haver Mood=Cnd|Number=Plur|Person=2|VerbForm=Fin
|
| 156 |
+
havia haver Mood=Ind|Number=Sing|Person=1|Tense=Imp|VerbForm=Fin
|
| 157 |
+
havia haver Mood=Ind|Number=Sing|Person=3|Tense=Imp|VerbForm=Fin
|
| 158 |
+
haviam haver Mood=Ind|Number=Plur|Person=3|Tense=Imp|VerbForm=Fin
|
| 159 |
+
havias haver Mood=Ind|Number=Sing|Person=2|Tense=Imp|VerbForm=Fin
|
| 160 |
+
havida haver Gender=Fem|Number=Sing|VerbForm=Part
|
| 161 |
+
havidas haver Gender=Fem|Number=Plur|VerbForm=Part
|
| 162 |
+
havido haver Gender=Masc|Number=Sing|VerbForm=Part
|
| 163 |
+
havidos haver Gender=Masc|Number=Plur|VerbForm=Part
|
| 164 |
+
havíamos haver Mood=Ind|Number=Plur|Person=1|Tense=Imp|VerbForm=Fin
|
| 165 |
+
havíeis haver Mood=Ind|Number=Plur|Person=2|Tense=Imp|VerbForm=Fin
|
| 166 |
+
hei haver Mood=Ind|Number=Sing|Person=1|Tense=Pres|VerbForm=Fin
|
| 167 |
+
houve haver Mood=Ind|Number=Sing|Person=1|Tense=Past|VerbForm=Fin
|
| 168 |
+
houve haver Mood=Ind|Number=Sing|Person=3|Tense=Past|VerbForm=Fin
|
| 169 |
+
houvemos haver Mood=Ind|Number=Plur|Person=1|Tense=Past|VerbForm=Fin
|
| 170 |
+
houver haver Mood=Sub|Number=Sing|Person=1|Tense=Fut|VerbForm=Fin
|
| 171 |
+
houver haver Mood=Sub|Number=Sing|Person=3|Tense=Fut|VerbForm=Fin
|
| 172 |
+
houvera haver Mood=Ind|Number=Sing|Person=1|Tense=Pqp|VerbForm=Fin
|
| 173 |
+
houvera haver Mood=Ind|Number=Sing|Person=3|Tense=Pqp|VerbForm=Fin
|
| 174 |
+
houveram haver Mood=Ind|Number=Plur|Person=3|Tense=Past|VerbForm=Fin
|
| 175 |
+
houveram haver Mood=Ind|Number=Plur|Person=3|Tense=Pqp|VerbForm=Fin
|
| 176 |
+
houveras haver Mood=Ind|Number=Sing|Person=2|Tense=Pqp|VerbForm=Fin
|
| 177 |
+
houverdes haver Mood=Sub|Number=Plur|Person=2|Tense=Fut|VerbForm=Fin
|
| 178 |
+
houverem haver Mood=Sub|Number=Plur|Person=3|Tense=Fut|VerbForm=Fin
|
| 179 |
+
houveres haver Mood=Sub|Number=Sing|Person=2|Tense=Fut|VerbForm=Fin
|
| 180 |
+
houvermos haver Mood=Sub|Number=Plur|Person=1|Tense=Fut|VerbForm=Fin
|
| 181 |
+
houvesse haver Mood=Sub|Number=Sing|Person=1|Tense=Past|VerbForm=Fin
|
| 182 |
+
houvesse haver Mood=Sub|Number=Sing|Person=3|Tense=Past|VerbForm=Fin
|
| 183 |
+
houvessem haver Mood=Sub|Number=Plur|Person=3|Tense=Past|VerbForm=Fin
|
| 184 |
+
houvesses haver Mood=Sub|Number=Sing|Person=2|Tense=Past|VerbForm=Fin
|
| 185 |
+
houveste haver Mood=Ind|Number=Sing|Person=2|Tense=Past|VerbForm=Fin
|
| 186 |
+
houvestes haver Mood=Ind|Number=Plur|Person=2|Tense=Past|VerbForm=Fin
|
| 187 |
+
houvéramos haver Mood=Ind|Number=Plur|Person=1|Tense=Pqp|VerbForm=Fin
|
| 188 |
+
houvéreis haver Mood=Ind|Number=Plur|Person=2|Tense=Pqp|VerbForm=Fin
|
| 189 |
+
houvésseis haver Mood=Sub|Number=Plur|Person=2|Tense=Past|VerbForm=Fin
|
| 190 |
+
houvéssemos haver Mood=Sub|Number=Plur|Person=1|Tense=Past|VerbForm=Fin
|
| 191 |
+
há haver Mood=Imp|Number=Sing|Person=2|VerbForm=Fin
|
| 192 |
+
há haver Mood=Ind|Number=Sing|Person=3|Tense=Pres|VerbForm=Fin
|
| 193 |
+
hás haver Mood=Ind|Number=Sing|Person=2|Tense=Pres|VerbForm=Fin
|
| 194 |
+
hão haver Mood=Ind|Number=Plur|Person=3|Tense=Pres|VerbForm=Fin
|
| 195 |
+
ia ir Mood=Ind|Number=Sing|Person=1|Tense=Imp|VerbForm=Fin
|
| 196 |
+
ia ir Mood=Ind|Number=Sing|Person=3|Tense=Imp|VerbForm=Fin
|
| 197 |
+
iam ir Mood=Ind|Number=Plur|Person=3|Tense=Imp|VerbForm=Fin
|
| 198 |
+
ias ir Mood=Ind|Number=Sing|Person=2|Tense=Imp|VerbForm=Fin
|
| 199 |
+
ida ir Gender=Fem|Number=Sing|VerbForm=Part
|
| 200 |
+
idas ir Gender=Fem|Number=Plur|VerbForm=Part
|
| 201 |
+
ide ir Mood=Imp|Number=Plur|Person=2|VerbForm=Fin
|
| 202 |
+
ides ir Mood=Ind|Number=Plur|Person=2|Tense=Pres|VerbForm=Fin
|
| 203 |
+
ido ir Gender=Masc|Number=Sing|VerbForm=Part
|
| 204 |
+
idos ir Gender=Masc|Number=Plur|VerbForm=Part
|
| 205 |
+
indo ir VerbForm=Ger
|
| 206 |
+
ir ir Number=Sing|Person=1|VerbForm=Inf
|
| 207 |
+
ir ir Number=Sing|Person=3|VerbForm=Inf
|
| 208 |
+
ir ir VerbForm=Inf
|
| 209 |
+
irdes ir Number=Plur|Person=2|VerbForm=Inf
|
| 210 |
+
irei ir Mood=Ind|Number=Sing|Person=1|Tense=Fut|VerbForm=Fin
|
| 211 |
+
ireis ir Mood=Ind|Number=Plur|Person=2|Tense=Fut|VerbForm=Fin
|
| 212 |
+
irem ir Number=Plur|Person=3|VerbForm=Inf
|
| 213 |
+
iremos ir Mood=Ind|Number=Plur|Person=1|Tense=Fut|VerbForm=Fin
|
| 214 |
+
ires ir Number=Sing|Person=2|VerbForm=Inf
|
| 215 |
+
iria ir Mood=Cnd|Number=Sing|Person=1|VerbForm=Fin
|
| 216 |
+
iria ir Mood=Cnd|Number=Sing|Person=3|VerbForm=Fin
|
| 217 |
+
iriam ir Mood=Cnd|Number=Plur|Person=3|VerbForm=Fin
|
| 218 |
+
irias ir Mood=Cnd|Number=Sing|Person=2|VerbForm=Fin
|
| 219 |
+
irmos ir Number=Plur|Person=1|VerbForm=Inf
|
| 220 |
+
irá ir Mood=Ind|Number=Sing|Person=3|Tense=Fut|VerbForm=Fin
|
| 221 |
+
irás ir Mood=Ind|Number=Sing|Person=2|Tense=Fut|VerbForm=Fin
|
| 222 |
+
irão ir Mood=Ind|Number=Plur|Person=3|Tense=Fut|VerbForm=Fin
|
| 223 |
+
iríamos ir Mood=Cnd|Number=Plur|Person=1|VerbForm=Fin
|
| 224 |
+
iríeis ir Mood=Cnd|Number=Plur|Person=2|VerbForm=Fin
|
| 225 |
+
sede ser Mood=Imp|Number=Plur|Person=2|VerbForm=Fin
|
| 226 |
+
seja ser Mood=Imp|Number=Sing|Person=3|VerbForm=Fin
|
| 227 |
+
seja ser Mood=Sub|Number=Sing|Person=1|Tense=Pres|VerbForm=Fin
|
| 228 |
+
seja ser Mood=Sub|Number=Sing|Person=3|Tense=Pres|VerbForm=Fin
|
| 229 |
+
sejais ser Mood=Sub|Number=Plur|Person=2|Tense=Pres|VerbForm=Fin
|
| 230 |
+
sejam ser Mood=Imp|Number=Plur|Person=3|VerbForm=Fin
|
| 231 |
+
sejam ser Mood=Sub|Number=Plur|Person=3|Tense=Pres|VerbForm=Fin
|
| 232 |
+
sejamos ser Mood=Imp|Number=Plur|Person=1|VerbForm=Fin
|
| 233 |
+
sejamos ser Mood=Sub|Number=Plur|Person=1|Tense=Pres|VerbForm=Fin
|
| 234 |
+
sejas ser Mood=Sub|Number=Sing|Person=2|Tense=Pres|VerbForm=Fin
|
| 235 |
+
sendo ser VerbForm=Ger
|
| 236 |
+
ser ser Number=Sing|Person=1|VerbForm=Inf
|
| 237 |
+
ser ser Number=Sing|Person=3|VerbForm=Inf
|
| 238 |
+
ser ser VerbForm=Inf
|
| 239 |
+
serdes ser Number=Plur|Person=2|VerbForm=Inf
|
| 240 |
+
serei ser Mood=Ind|Number=Sing|Person=1|Tense=Fut|VerbForm=Fin
|
| 241 |
+
sereis ser Mood=Ind|Number=Plur|Person=2|Tense=Fut|VerbForm=Fin
|
| 242 |
+
serem ser Number=Plur|Person=3|VerbForm=Inf
|
| 243 |
+
seremos ser Mood=Ind|Number=Plur|Person=1|Tense=Fut|VerbForm=Fin
|
| 244 |
+
seres ser Number=Sing|Person=2|VerbForm=Inf
|
| 245 |
+
seria ser Mood=Cnd|Number=Sing|Person=1|VerbForm=Fin
|
| 246 |
+
seria ser Mood=Cnd|Number=Sing|Person=3|VerbForm=Fin
|
| 247 |
+
seriam ser Mood=Cnd|Number=Plur|Person=3|VerbForm=Fin
|
| 248 |
+
serias ser Mood=Cnd|Number=Sing|Person=2|VerbForm=Fin
|
| 249 |
+
sermos ser Number=Plur|Person=1|VerbForm=Inf
|
| 250 |
+
será ser Mood=Ind|Number=Sing|Person=3|Tense=Fut|VerbForm=Fin
|
| 251 |
+
serás ser Mood=Ind|Number=Sing|Person=2|Tense=Fut|VerbForm=Fin
|
| 252 |
+
serão ser Mood=Ind|Number=Plur|Person=3|Tense=Fut|VerbForm=Fin
|
| 253 |
+
seríamos ser Mood=Cnd|Number=Plur|Person=1|VerbForm=Fin
|
| 254 |
+
seríeis ser Mood=Cnd|Number=Plur|Person=2|VerbForm=Fin
|
| 255 |
+
sida ser Gender=Fem|Number=Sing|VerbForm=Part
|
| 256 |
+
sidas ser Gender=Fem|Number=Plur|VerbForm=Part
|
| 257 |
+
sido ser Gender=Masc|Number=Sing|VerbForm=Part
|
| 258 |
+
sidos ser Gender=Masc|Number=Plur|VerbForm=Part
|
| 259 |
+
sois ser Mood=Ind|Number=Plur|Person=2|Tense=Pres|VerbForm=Fin
|
| 260 |
+
somos ser Mood=Ind|Number=Plur|Person=1|Tense=Pres|VerbForm=Fin
|
| 261 |
+
sou ser Mood=Ind|Number=Sing|Person=1|Tense=Pres|VerbForm=Fin
|
| 262 |
+
são ser Mood=Ind|Number=Plur|Person=3|Tense=Pres|VerbForm=Fin
|
| 263 |
+
sê ser Mood=Imp|Number=Sing|Person=2|VerbForm=Fin
|
| 264 |
+
tamos estar Abbr=Yes|Mood=Ind|Number=Plur|Person=1|Tense=Pres|VerbForm=Fin
|
| 265 |
+
tava estar Abbr=Yes|Mood=Ind|Number=Sing|Person=3|Tense=Imp|VerbForm=Fin
|
| 266 |
+
tavam estar Abbr=Yes|Mood=Ind|Number=Plur|Person=3|Tense=Imp|VerbForm=Fin
|
| 267 |
+
tem ter Mood=Imp|Number=Sing|Person=2|VerbForm=Fin
|
| 268 |
+
tem ter Mood=Ind|Number=Sing|Person=3|Tense=Pres|VerbForm=Fin
|
| 269 |
+
temos ter Mood=Ind|Number=Plur|Person=1|Tense=Pres|VerbForm=Fin
|
| 270 |
+
tende ter Mood=Imp|Number=Plur|Person=2|VerbForm=Fin
|
| 271 |
+
tendes ter Mood=Ind|Number=Plur|Person=2|Tense=Pres|VerbForm=Fin
|
| 272 |
+
tendo ter VerbForm=Ger
|
| 273 |
+
tenha ter Mood=Imp|Number=Sing|Person=3|VerbForm=Fin
|
| 274 |
+
tenha ter Mood=Sub|Number=Sing|Person=1|Tense=Pres|VerbForm=Fin
|
| 275 |
+
tenha ter Mood=Sub|Number=Sing|Person=3|Tense=Pres|VerbForm=Fin
|
| 276 |
+
tenhais ter Mood=Sub|Number=Plur|Person=2|Tense=Pres|VerbForm=Fin
|
| 277 |
+
tenham ter Mood=Imp|Number=Plur|Person=3|VerbForm=Fin
|
| 278 |
+
tenham ter Mood=Sub|Number=Plur|Person=3|Tense=Pres|VerbForm=Fin
|
| 279 |
+
tenhamos ter Mood=Imp|Number=Plur|Person=1|VerbForm=Fin
|
| 280 |
+
tenhamos ter Mood=Sub|Number=Plur|Person=1|Tense=Pres|VerbForm=Fin
|
| 281 |
+
tenhas ter Mood=Sub|Number=Sing|Person=2|Tense=Pres|VerbForm=Fin
|
| 282 |
+
tenho ter Mood=Ind|Number=Sing|Person=1|Tense=Pres|VerbForm=Fin
|
| 283 |
+
tens ter Mood=Ind|Number=Sing|Person=2|Tense=Pres|VerbForm=Fin
|
| 284 |
+
ter ter Number=Sing|Person=1|VerbForm=Inf
|
| 285 |
+
ter ter Number=Sing|Person=3|VerbForm=Inf
|
| 286 |
+
ter ter VerbForm=Inf
|
| 287 |
+
terdes ter Number=Plur|Person=2|VerbForm=Inf
|
| 288 |
+
terei ter Mood=Ind|Number=Sing|Person=1|Tense=Fut|VerbForm=Fin
|
| 289 |
+
tereis ter Mood=Ind|Number=Plur|Person=2|Tense=Fut|VerbForm=Fin
|
| 290 |
+
terem ter Number=Plur|Person=3|VerbForm=Inf
|
| 291 |
+
teremos ter Mood=Ind|Number=Plur|Person=1|Tense=Fut|VerbForm=Fin
|
| 292 |
+
teres ter Number=Sing|Person=2|VerbForm=Inf
|
| 293 |
+
teria ter Mood=Cnd|Number=Sing|Person=1|VerbForm=Fin
|
| 294 |
+
teria ter Mood=Cnd|Number=Sing|Person=3|VerbForm=Fin
|
| 295 |
+
teriam ter Mood=Cnd|Number=Plur|Person=3|VerbForm=Fin
|
| 296 |
+
terias ter Mood=Cnd|Number=Sing|Person=2|VerbForm=Fin
|
| 297 |
+
termos ter Number=Plur|Person=1|VerbForm=Inf
|
| 298 |
+
terá ter Mood=Ind|Number=Sing|Person=3|Tense=Fut|VerbForm=Fin
|
| 299 |
+
terás ter Mood=Ind|Number=Sing|Person=2|Tense=Fut|VerbForm=Fin
|
| 300 |
+
terão ter Mood=Ind|Number=Plur|Person=3|Tense=Fut|VerbForm=Fin
|
| 301 |
+
teríamos ter Mood=Cnd|Number=Plur|Person=1|VerbForm=Fin
|
| 302 |
+
teríeis ter Mood=Cnd|Number=Plur|Person=2|VerbForm=Fin
|
| 303 |
+
teve ter Mood=Ind|Number=Sing|Person=3|Tense=Past|VerbForm=Fin
|
| 304 |
+
tida ter Gender=Fem|Number=Sing|VerbForm=Part
|
| 305 |
+
tidas ter Gender=Fem|Number=Plur|VerbForm=Part
|
| 306 |
+
tido ter Gender=Masc|Number=Sing|VerbForm=Part
|
| 307 |
+
tidos ter Gender=Masc|Number=Plur|VerbForm=Part
|
| 308 |
+
tinha ter Mood=Ind|Number=Sing|Person=1|Tense=Imp|VerbForm=Fin
|
| 309 |
+
tinha ter Mood=Ind|Number=Sing|Person=3|Tense=Imp|VerbForm=Fin
|
| 310 |
+
tinham ter Mood=Ind|Number=Plur|Person=3|Tense=Imp|VerbForm=Fin
|
| 311 |
+
tinhas: ter Mood=Ind|Number=Sing|Person=2|Tense=Imp|VerbForm=Fin
|
| 312 |
+
tive ter Mood=Ind|Number=Sing|Person=1|Tense=Past|VerbForm=Fin
|
| 313 |
+
tivemos ter Mood=Ind|Number=Plur|Person=1|Tense=Past|VerbForm=Fin
|
| 314 |
+
tiver ter Mood=Sub|Number=Sing|Person=1|Tense=Fut|VerbForm=Fin
|
| 315 |
+
tiver ter Mood=Sub|Number=Sing|Person=3|Tense=Fut|VerbForm=Fin
|
| 316 |
+
tivera ter Mood=Ind|Number=Sing|Person=1|Tense=Pqp|VerbForm=Fin
|
| 317 |
+
tivera ter Mood=Ind|Number=Sing|Person=3|Tense=Pqp|VerbForm=Fin
|
| 318 |
+
tiveram ter Mood=Ind|Number=Plur|Person=3|Tense=Past|VerbForm=Fin
|
| 319 |
+
tiveram ter Mood=Ind|Number=Plur|Person=3|Tense=Pqp|VerbForm=Fin
|
| 320 |
+
tiveras ter Mood=Ind|Number=Sing|Person=2|Tense=Pqp|VerbForm=Fin
|
| 321 |
+
tiverdes ter Mood=Sub|Number=Plur|Person=2|Tense=Fut|VerbForm=Fin
|
| 322 |
+
tiverem ter Mood=Sub|Number=Plur|Person=3|Tense=Fut|VerbForm=Fin
|
| 323 |
+
tiveres ter Mood=Sub|Number=Sing|Person=2|Tense=Fut|VerbForm=Fin
|
| 324 |
+
tivermos ter Mood=Sub|Number=Plur|Person=1|Tense=Fut|VerbForm=Fin
|
| 325 |
+
tivesse ter Mood=Sub|Number=Sing|Person=1|Tense=Past|VerbForm=Fin
|
| 326 |
+
tivesse ter Mood=Sub|Number=Sing|Person=3|Tense=Past|VerbForm=Fin
|
| 327 |
+
tivessem ter Mood=Sub|Number=Plur|Person=3|Tense=Past|VerbForm=Fin
|
| 328 |
+
tivesses ter Mood=Sub|Number=Sing|Person=2|Tense=Past|VerbForm=Fin
|
| 329 |
+
tiveste ter Mood=Ind|Number=Sing|Person=2|Tense=Past|VerbForm=Fin
|
| 330 |
+
tivestes ter Mood=Ind|Number=Plur|Person=2|Tense=Past|VerbForm=Fin
|
| 331 |
+
tivéramos ter Mood=Ind|Number=Plur|Person=1|Tense=Pqp|VerbForm=Fin
|
| 332 |
+
tivéreis ter Mood=Ind|Number=Plur|Person=2|Tense=Pqp|VerbForm=Fin
|
| 333 |
+
tivésseis ter Mood=Sub|Number=Plur|Person=2|Tense=Past|VerbForm=Fin
|
| 334 |
+
tivéssemos ter Mood=Sub|Number=Plur|Person=1|Tense=Past|VerbForm=Fin
|
| 335 |
+
tá estar Abbr=Yes|Mood=Ind|Number=Sing|Person=3|Tense=Pres|VerbForm=Fin
|
| 336 |
+
tão estar Abbr=Yes|Abbr=Yes|Mood=Ind|Number=Plur|Person=3|Tense=Pres|VerbForm=Fin
|
| 337 |
+
têm ter Mood=Ind|Number=Plur|Person=3|Tense=Pres|VerbForm=Fin
|
| 338 |
+
tínhamos ter Mood=Ind|Number=Plur|Person=1|Tense=Imp|VerbForm=Fin
|
| 339 |
+
tínheis ter Mood=Ind|Number=Plur|Person=2|Tense=Imp|VerbForm=Fin
|
| 340 |
+
tô estar Abbr=Yes|Mood=Ind|Number=Sing|Person=1|Tense=Pres|VerbForm=Fin
|
| 341 |
+
vades ir Mood=Sub|Number=Plur|Person=2|Tense=Pres|VerbForm=Fin
|
| 342 |
+
vai ir Mood=Imp|Number=Sing|Person=2|VerbForm=Fin
|
| 343 |
+
vai ir Mood=Ind|Number=Sing|Person=3|Tense=Pres|VerbForm=Fin
|
| 344 |
+
vais ir Mood=Ind|Number=Sing|Person=2|Tense=Pres|VerbForm=Fin
|
| 345 |
+
vamo ir Abbr=Yes|Mood=Imp|Number=Plur|Person=1|VerbForm=Fin
|
| 346 |
+
vamo ir Abbr=Yes|Mood=Ind|Number=Plur|Person=1|Tense=Pres|VerbForm=Fin
|
| 347 |
+
vamo ir Abbr=Yes|Mood=Sub|Number=Plur|Person=1|Tense=Pres|VerbForm=Fin
|
| 348 |
+
vamos ir Mood=Imp|Number=Plur|Person=1|VerbForm=Fin
|
| 349 |
+
vamos ir Mood=Ind|Number=Plur|Person=1|Tense=Pres|VerbForm=Fin
|
| 350 |
+
vamos ir Mood=Sub|Number=Plur|Person=1|Tense=Pres|VerbForm=Fin
|
| 351 |
+
veio vir Mood=Ind|Number=Sing|Person=3|Tense=Past|VerbForm=Fin
|
| 352 |
+
vem vir Mood=Imp|Number=Sing|Person=2|VerbForm=Fin
|
| 353 |
+
vem vir Mood=Ind|Number=Sing|Person=3|Tense=Pres|VerbForm=Fin
|
| 354 |
+
venha vir Mood=Imp|Number=Sing|Person=3|VerbForm=Fin
|
| 355 |
+
venha vir Mood=Sub|Number=Sing|Person=1|Tense=Pres|VerbForm=Fin
|
| 356 |
+
venha vir Mood=Sub|Number=Sing|Person=3|Tense=Pres|VerbForm=Fin
|
| 357 |
+
venhais vir Mood=Sub|Number=Plur|Person=2|Tense=Pres|VerbForm=Fin
|
| 358 |
+
venham vir Mood=Imp|Number=Plur|Person=3|VerbForm=Fin
|
| 359 |
+
venham vir Mood=Sub|Number=Plur|Person=3|Tense=Pres|VerbForm=Fin
|
| 360 |
+
venhamos vir Mood=Imp|Number=Plur|Person=1|VerbForm=Fin
|
| 361 |
+
venhamos vir Mood=Sub|Number=Plur|Person=1|Tense=Pres|VerbForm=Fin
|
| 362 |
+
venhas vir Mood=Sub|Number=Sing|Person=2|Tense=Pres|VerbForm=Fin
|
| 363 |
+
venho vir Mood=Ind|Number=Sing|Person=1|Tense=Pres|VerbForm=Fin
|
| 364 |
+
vens: vir Mood=Ind|Number=Sing|Person=2|Tense=Pres|VerbForm=Fin
|
| 365 |
+
viemos vir Mood=Ind|Number=Plur|Person=1|Tense=Past|VerbForm=Fin
|
| 366 |
+
vier vir Mood=Sub|Number=Sing|Person=1|Tense=Fut|VerbForm=Fin
|
| 367 |
+
vier vir Mood=Sub|Number=Sing|Person=3|Tense=Fut|VerbForm=Fin
|
| 368 |
+
viera vir Mood=Ind|Number=Sing|Person=1|Tense=Pqp|VerbForm=Fin
|
| 369 |
+
viera vir Mood=Ind|Number=Sing|Person=3|Tense=Pqp|VerbForm=Fin
|
| 370 |
+
vieram vir Mood=Ind|Number=Plur|Person=3|Tense=Past|VerbForm=Fin
|
| 371 |
+
vieram vir Mood=Ind|Number=Plur|Person=3|Tense=Pqp|VerbForm=Fin
|
| 372 |
+
vieras vir Mood=Ind|Number=Sing|Person=2|Tense=Pqp|VerbForm=Fin
|
| 373 |
+
vierdes vir Mood=Sub|Number=Plur|Person=2|Tense=Fut|VerbForm=Fin
|
| 374 |
+
vierem vir Mood=Sub|Number=Plur|Person=3|Tense=Fut|VerbForm=Fin
|
| 375 |
+
vieres vir Mood=Sub|Number=Sing|Person=2|Tense=Fut|VerbForm=Fin
|
| 376 |
+
viermos vir Mood=Sub|Number=Plur|Person=1|Tense=Fut|VerbForm=Fin
|
| 377 |
+
viesse vir Mood=Sub|Number=Sing|Person=1|Tense=Past|VerbForm=Fin
|
| 378 |
+
viesse vir Mood=Sub|Number=Sing|Person=3|Tense=Past|VerbForm=Fin
|
| 379 |
+
viessem vir Mood=Sub|Number=Plur|Person=3|Tense=Past|VerbForm=Fin
|
| 380 |
+
viesses vir Mood=Sub|Number=Sing|Person=2|Tense=Past|VerbForm=Fin
|
| 381 |
+
vieste vir Mood=Ind|Number=Sing|Person=2|Tense=Past|VerbForm=Fin
|
| 382 |
+
viestes vir Mood=Ind|Number=Plur|Person=2|Tense=Past|VerbForm=Fin
|
| 383 |
+
vim vir Mood=Ind|Number=Sing|Person=1|Tense=Past|VerbForm=Fin
|
| 384 |
+
vimos vir Mood=Ind|Number=Plur|Person=1|Tense=Pres|VerbForm=Fin
|
| 385 |
+
vinda vir Gender=Fem|Number=Sing|VerbForm=Part
|
| 386 |
+
vindas vir Gender=Fem|Number=Plur|VerbForm=Part
|
| 387 |
+
vinde vir Mood=Imp|Number=Plur|Person=2|VerbForm=Fin
|
| 388 |
+
vindes vir Mood=Ind|Number=Plur|Person=2|Tense=Pres|VerbForm=Fin
|
| 389 |
+
vindo vir Gender=Masc|Number=Sing|VerbForm=Part
|
| 390 |
+
vindo vir VerbForm=Ger
|
| 391 |
+
vindos vir Gender=Masc|Number=Plur|VerbForm=Part
|
| 392 |
+
vinha vir Mood=Ind|Number=Sing|Person=1|Tense=Imp|VerbForm=Fin
|
| 393 |
+
vinha vir Mood=Ind|Number=Sing|Person=3|Tense=Imp|VerbForm=Fin
|
| 394 |
+
vinham vir Mood=Ind|Number=Plur|Person=3|Tense=Imp|VerbForm=Fin
|
| 395 |
+
vinhas: vir Mood=Ind|Number=Sing|Person=2|Tense=Imp|VerbForm=Fin
|
| 396 |
+
vir vir Number=Sing|Person=1|VerbForm=Inf
|
| 397 |
+
vir vir Number=Sing|Person=3|VerbForm=Inf
|
| 398 |
+
vir vir VerbForm=Inf
|
| 399 |
+
virdes vir Number=Plur|Person=2|VerbForm=Inf
|
| 400 |
+
virei vir Mood=Ind|Number=Sing|Person=1|Tense=Fut|VerbForm=Fin
|
| 401 |
+
vireis vir Mood=Ind|Number=Plur|Person=2|Tense=Fut|VerbForm=Fin
|
| 402 |
+
virem vir Number=Plur|Person=3|VerbForm=Inf
|
| 403 |
+
viremos vir Mood=Ind|Number=Plur|Person=1|Tense=Fut|VerbForm=Fin
|
| 404 |
+
vires vir Number=Sing|Person=2|VerbForm=Inf
|
| 405 |
+
viria vir Mood=Cnd|Number=Sing|Person=1|VerbForm=Fin
|
| 406 |
+
viria vir Mood=Cnd|Number=Sing|Person=3|VerbForm=Fin
|
| 407 |
+
viriam vir Mood=Cnd|Number=Plur|Person=3|VerbForm=Fin
|
| 408 |
+
virias vir Mood=Cnd|Number=Sing|Person=2|VerbForm=Fin
|
| 409 |
+
virmos vir Number=Plur|Person=1|VerbForm=Inf
|
| 410 |
+
virá vir Mood=Ind|Number=Sing|Person=3|Tense=Fut|VerbForm=Fin
|
| 411 |
+
virás vir Mood=Ind|Number=Sing|Person=2|Tense=Fut|VerbForm=Fin
|
| 412 |
+
virão vir Mood=Ind|Number=Plur|Person=3|Tense=Fut|VerbForm=Fin
|
| 413 |
+
viríamos vir Mood=Cnd|Number=Plur|Person=1|VerbForm=Fin
|
| 414 |
+
viríeis vir Mood=Cnd|Number=Plur|Person=2|VerbForm=Fin
|
| 415 |
+
viéramos vir Mood=Ind|Number=Plur|Person=1|Tense=Pqp|VerbForm=Fin
|
| 416 |
+
viéreis vir Mood=Ind|Number=Plur|Person=2|Tense=Pqp|VerbForm=Fin
|
| 417 |
+
viésseis vir Mood=Sub|Number=Plur|Person=2|Tense=Past|VerbForm=Fin
|
| 418 |
+
viéssemos vir Mood=Sub|Number=Plur|Person=1|Tense=Past|VerbForm=Fin
|
| 419 |
+
vou ir Mood=Ind|Number=Sing|Person=1|Tense=Pres|VerbForm=Fin
|
| 420 |
+
vá ir Mood=Imp|Number=Sing|Person=3|VerbForm=Fin
|
| 421 |
+
vá ir Mood=Sub|Number=Sing|Person=1|Tense=Pres|VerbForm=Fin
|
| 422 |
+
vá ir Mood=Sub|Number=Sing|Person=3|Tense=Pres|VerbForm=Fin
|
| 423 |
+
vás ir Mood=Sub|Number=Sing|Person=2|Tense=Pres|VerbForm=Fin
|
| 424 |
+
vão ir Mood=Imp|Number=Plur|Person=3|VerbForm=Fin
|
| 425 |
+
vão ir Mood=Ind|Number=Plur|Person=3|Tense=Pres|VerbForm=Fin
|
| 426 |
+
vão ir Mood=Sub|Number=Plur|Person=3|Tense=Pres|VerbForm=Fin
|
| 427 |
+
vêm vir Mood=Ind|Number=Plur|Person=3|Tense=Pres|VerbForm=Fin
|
| 428 |
+
vínhamos vir Mood=Ind|Number=Plur|Person=1|Tense=Imp|VerbForm=Fin
|
| 429 |
+
vínheis vir Mood=Ind|Number=Plur|Person=2|Tense=Imp|VerbForm=Fin
|
| 430 |
+
é ser Mood=Ind|Number=Sing|Person=3|Tense=Pres|VerbForm=Fin
|
| 431 |
+
éramos ser Mood=Ind|Number=Plur|Person=1|Tense=Imp|VerbForm=Fin
|
| 432 |
+
éreis ser Mood=Ind|Number=Plur|Person=2|Tense=Imp|VerbForm=Fin
|
| 433 |
+
és ser Mood=Ind|Number=Sing|Person=2|Tense=Pres|VerbForm=Fin
|
| 434 |
+
íamos ir Mood=Ind|Number=Plur|Person=1|Tense=Imp|VerbForm=Fin
|
| 435 |
+
íeis ir Mood=Ind|Number=Plur|Person=2|Tense=Imp|VerbForm=Fin
|
src/portTokenizer/CCONJ.tsv
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
como como _
|
| 2 |
+
contudo contudo _
|
| 3 |
+
e e _
|
| 4 |
+
enquanto enquanto _
|
| 5 |
+
entretanto entretanto _
|
| 6 |
+
então então _
|
| 7 |
+
já já _
|
| 8 |
+
logo logo _
|
| 9 |
+
mas mas _
|
| 10 |
+
nem nem _
|
| 11 |
+
ora ora _
|
| 12 |
+
ou ou _
|
| 13 |
+
pois pois _
|
| 14 |
+
porquanto porquanto _
|
| 15 |
+
porque porque _
|
| 16 |
+
portanto portanto _
|
| 17 |
+
porém porém _
|
| 18 |
+
quando quando _
|
| 19 |
+
quanto quanto _
|
| 20 |
+
que que _
|
| 21 |
+
quer quer _
|
| 22 |
+
seja seja _
|
| 23 |
+
senão senão _
|
| 24 |
+
tanto tanto _
|
| 25 |
+
todavia todavia _
|