Skip to content
Snippets Groups Projects
Commit b00b9d47 authored by Christian Boulanger's avatar Christian Boulanger
Browse files

Add llamore gold data

parent 5319453e
No related branches found
No related tags found
No related merge requests found
Showing
with 19679 additions and 375 deletions
%% Cell type:code id: tags:
``` python
from lxml import etree
import os
import glob
def insert_cited_range(file_path):
parser = etree.XMLParser(remove_blank_text=False, strip_cdata=False, resolve_entities=False)
tree = etree.parse(file_path, parser)
root = tree.getroot()
ns = {
'tei': 'http://www.tei-c.org/ns/1.0',
'llamore': 'https://gitlab.mpcdf.mpg.de/dcfidalgo/llamore'
}
instances = root.findall(".//llamore:instance", ns)
for instance in instances:
bibls = instance.findall(".//llamore:output[@type='bibl']//tei:bibl", ns)
biblStructs = instance.findall(".//llamore:output[@type='biblStruct']//tei:biblStruct", ns)
# Make sure bibl and biblStruct have the same length
if len(bibls) != len(biblStructs):
id = instance.attrib.get('{http://www.w3.org/XML/1998/namespace}id')
print(f'<bibl> and <biblStruct> have unequal length in {id}')
continue
# Iterate over bibl and biblStruct, as they are paired by their indices
for bibl, biblStruct in zip(bibls, biblStructs):
bibl_citedRanges = bibl.findall(".//tei:citedRange", ns)
#biblStruct_monogr = biblStruct.find(".//tei:monogr", ns)
biblStruct_citedRange = biblStruct.find('.//tei:citedRange', ns)
if biblStruct_citedRange is None:
for bibl_citedRange in bibl_citedRanges:
# Copy the citedRange to biblStruct[last_element]
copied_bibl_citedRange = etree.Element("citedRange")
copied_bibl_citedRange.text = bibl_citedRange.text
copied_bibl_citedRange.attrib.update(bibl_citedRange.attrib)
copied_bibl_citedRange.tail = biblStruct.tail
biblStruct.append(copied_bibl_citedRange)
# Open the file in write mode and update its content
#file_path = file_path.replace(".xml", ".mod")
with open(file_path, 'w') as file:
file.write(etree.tostring(root, pretty_print=False, encoding='utf-8').decode())
# Get a list of all XML files in the directory
for filename in glob.glob("../data/gold/*.xml"):
print(filename)
insert_cited_range(filename)
```
%% Output
../data/gold\10.1111_1467-6478.00057.xml
../data/gold\10.1111_1467-6478.00080.xml
../data/gold\10.1515_zfrs-1980-0103.xml
../data/gold\10.1515_zfrs-1980-0104.xml
%% Cell type:markdown id: tags:
Regexes to rewrite xml structure:
S: `( +)<input type="formatted">(\n +)(\d+) ([\s\S]+?)(\n +)</input>`
R: `$1<output type="footnote">$2<note type="footnote" n="$3" xmlns="http://www.tei-c.org/ns/1.0">$2 <label>$3</label>$2<seg>$4</seg>$5</note>\n$1</output>`
%% Cell type:markdown id: tags:
%% Cell type:code id: tags:
``` python
# In <output type=bibl>, change <p> to <note> and add <label>
from lxml import etree
import os
import glob
from copy import deepcopy
def insert_footnote_metadata(file_path):
parser = etree.XMLParser(remove_blank_text=False, strip_cdata=False, resolve_entities=False)
tree = etree.parse(file_path, parser)
root = tree.getroot()
ns = {
'tei': 'http://www.tei-c.org/ns/1.0',
'llamore': 'https://gitlab.mpcdf.mpg.de/dcfidalgo/llamore'
}
instances = root.findall(".//llamore:instance", ns)
for instance in instances:
id = instance.attrib.get('{http://www.w3.org/XML/1998/namespace}id')
outp_footnote = instance.find(".//llamore:output[@type='footnote']", ns)
outp_bibl = instance.find(".//llamore:output[@type='bibl']", ns)
outp_bibstruct = instance.find(".//llamore:output[@type='biblStruct']", ns)
if outp_footnote is None:
print(f'No footnote output in {id}')
continue
note = outp_footnote.find("./tei:note", ns)
if note is not None:
note.attrib['place'] = "bottom"
n= note.attrib.get('n', None)
if n is not None:
bibl_p = outp_bibl.find(".//tei:p", ns)
if bibl_p is None:
print(f"no <p> in footnote {n}")
else:
bibl_p.tag = "note"
bibl_p.attrib['n'] = n
bibl_p.attrib['type'] = "footnote"
bibl_p.attrib['place'] = "bottom"
label= outp_footnote.find("./tei:note/tei:label", ns)
if label is not None:
bibl_p.insert(0, deepcopy(label))
# Open the file in write mode and update its content
#file_path = file_path.replace(".xml", "-mod.xml")
with open(file_path, 'w') as file:
file.write(etree.tostring(root, pretty_print=False, encoding='utf-8').decode())
# Get a list of all XML files in the directory
for filename in glob.glob("../data/gold/*.xml"):
print(filename)
insert_footnote_metadata(filename)
```
%% Output
../data/gold/10.1515_zfrs-1980-0103.xml
../data/gold/10.1515_zfrs-1980-0104.xml
../data/gold/10.1111_1467-6478.00080.xml
../data/gold/10.1111_1467-6478.00057.xml
%% Cell type:code id: tags:
``` python
# In <output type=footnote>, insert segmentation without semantics
from lxml import etree
import os
import regex as re
import glob
from copy import deepcopy
import textwrap
ns = {
'tei': 'http://www.tei-c.org/ns/1.0',
'llamore': 'https://gitlab.mpcdf.mpg.de/dcfidalgo/llamore'
}
def add_tei_prefix(tag):
return f'{{{ns["tei"]}}}{tag}'
def get_element_text_content(elem):
return remove_whitespace(etree.tostring(elem, method="text", encoding="unicode"))
def indentation_level(element):
level = 0
while element is not None:
element = element.getparent()
level += 1
return level - 1
def prettify_content(elem: etree._Element, indentation=" ", width=120):
text = re.sub(r'\s+', ' ', elem.text, flags=re.MULTILINE)
lines = textwrap.wrap(text, width=width)
indent = indentation_level(elem) * indentation
lines = [ indent + indentation + line for line in lines ]
lines.insert(0, "")
lines.append(indent)
elem.text = '\n'.join(lines)
def fix_indentation(elem, level=0, indentation=" "):
indent = "\n" + level*indentation
if len(elem):
if not elem.text or not elem.text.strip():
elem.text = indent + " "
if not elem.tail or not elem.tail.strip():
elem.tail = indent
for elem in elem:
fix_indentation(elem, level+1, indentation)
if not elem.tail or not elem.tail.strip():
elem.tail = indent
else:
if level and (not elem.tail or not elem.tail.strip()):
elem.tail = indent
def remove_whitespace(text):
# we need to remove the whitespace that comes with the indentation of pretty-printed xml
text = re.sub(r'\n\s*', ' ', text)
# reduce double spaces to one
while re.search(r'\s\s', text):
text = re.sub(r'\s\s', ' ', text)
# escape character sequences which would be corrupted by whitespace removal rules
text = re.sub(r'\. \. \.', '[!spaced_elipsis!]', text)
# fix issues with whitespace before punctuation
text = re.sub(r' ([.;,!?%:])( |$)', r'\1 ', text)
# opening and closing punctutation, such as brackets
text = re.sub(r'(\p{Ps}) ', r'\1', text)
text = re.sub(r' (\p{Pe})', r'\1', text)
# opening and closing quotes
text = re.sub(r'(\p{Pi}) ', r'\1', text)
text = re.sub(r' (\p{Pf})', r'\1', text)
# slash
text = re.sub(r' ?/ ?', r'/', text)
# hyphen
text = re.sub(r'([^ ])- ', r'\1-', text)
# restore sequences
text = text.replace('[!spaced_elipsis!]', r'. . .')
return text.strip()
def create_children_from_text_content(element, tag, text_array):
normalized_content = get_element_text_content(element)
local_name = etree.QName(element).localname
for string in text_array:
normalized_string = remove_whitespace(string)
if normalized_string in normalized_content:
tagged_string = f'<{tag}>{normalized_string}</{tag}>'
if tagged_string not in normalized_content and len(string) > 20:
normalized_content = normalized_content.replace(normalized_string, tagged_string)
else:
print(f'The string "{normalized_string}" was not found in "{normalized_content}"')
continue
normalized_content = f'<{local_name} xmlns="{ns["tei"]}">{normalized_content}</{local_name}>'
parser = etree.XMLParser(ns_clean=True, recover=True, remove_blank_text=True, resolve_entities=False)
new_element = etree.fromstring(normalized_content, parser=parser)
# put all content in child nodes
for child in new_element:
if etree.QName(child).localname != tag and child.tail is not None and child.tail.strip() != "":
new_child = etree.Element("seg")
new_child.text = child.tail.strip()
new_element.insert(new_element.index(child)+1, new_child)
child.tail = ''
if new_element.text and new_element.text != "":
first_child = etree.Element("seg")
first_child.text = new_element.text.strip()
new_element.insert(0, first_child)
new_element.text = ''
if new_element.tail and new_element.tail != "":
last_child = etree.Element("seg")
last_child.text = new_element.tail.strip()
new_element.append(last_child)
new_element.tail = ''
return new_element
def segment_footnote_string(file_path):
parser = etree.XMLParser(remove_blank_text=False, strip_cdata=False, resolve_entities=False)
tree = etree.parse(file_path, parser)
root = tree.getroot()
instances = root.findall(".//llamore:instance", ns)
for instance in instances:
id = instance.attrib.get('{http://www.w3.org/XML/1998/namespace}id')
outp_footnote = instance.find(".//llamore:output[@type='footnote']", ns)
outp_footnote.attrib['type'] = "components"
outp_fn_note = outp_footnote.find("./tei:note", ns)
note_seg = outp_fn_note.find("./tei:seg", ns)
# bibl
bibls = instance.findall(".//llamore:output[@type='bibl']//tei:bibl", ns)
bibl_text_contents = [get_element_text_content(bibl) for bibl in bibls]
new_seg = create_children_from_text_content(note_seg, 'bibl', bibl_text_contents)
for elem in new_seg:
outp_fn_note.append(elem)
outp_fn_note.remove(note_seg)
fix_indentation(outp_footnote, 4, " ")
# check
raw_text = remove_whitespace(instance.find(".//llamore:input[@type='raw']", ns).text.strip())
components_text = get_element_text_content(outp_footnote)
if raw_text.strip() != components_text:
print(f'Text mismatch in {id}:\n{raw_text}\n{components_text}')
# Open the file in write mode and update its content
#file_path = file_path.replace(".xml", "-mod.xml")
with open(file_path, 'w') as file:
file.write(etree.tostring(root, pretty_print=False, encoding='utf-8').decode())
# Get a list of all XML files in the directory
for filename in glob.glob("../data/gold/*.xml"):
if not filename.endswith("-mod.xml"):
print(filename)
segment_footnote_string(filename)
```
%% Output
../data/gold/10.1515_zfrs-1980-0103.xml
../data/gold/10.1515_zfrs-1980-0104.xml
Text mismatch in instance-9:
9 Macaulay, Elegant Models, Empirical Pictures, and the Complexities of Contract, Law & Soc. Rev. 11 (1977) 507 ff.
9 Macaulay, Elegant Models, Empirical Pictures, and the Complexities of Contract, Law Soc. Rev. 11 (1977) 507 ff.
../data/gold/10.1111_1467-6478.00080.xml
../data/gold/10.1111_1467-6478.00057.xml
Source diff could not be displayed: it is too large. Options to address this: view the blob.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema version="1.0"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:tei="http://www.tei-c.org/ns/1.0"
xmlns:llamore="https://gitlab.mpcdf.mpg.de/dcfidalgo/llamore"
targetNamespace="https://gitlab.mpcdf.mpg.de/dcfidalgo/llamore"
elementFormDefault="qualified">
<xsd:import namespace="http://www.tei-c.org/ns/1.0" schemaLocation="document.xsd"/>
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="http://www.w3.org/2001/xml.xsd"/>
<xsd:element name="dataset">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="instance" maxOccurs="unbounded">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="input" maxOccurs="unbounded">
<xsd:complexType>
<xsd:simpleContent>
<xsd:extension base="xsd:string">
<xsd:attribute name="type" type="xsd:string"/>
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>
</xsd:element>
<xsd:element name="output" maxOccurs="unbounded">
<xsd:complexType>
<xsd:sequence minOccurs="0">
<xsd:element ref="tei:p" minOccurs="0"/>
<xsd:element ref="tei:listBibl" minOccurs="0"/>
<xsd:element ref="tei:note" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="type" type="xsd:string"/>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
<xsd:attribute ref="xml:id"/>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
This diff is collapsed.
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://www.w3.org/XML/1998/namespace" xmlns:tei="http://www.tei-c.org/ns/1.0">
<xs:import namespace="http://www.tei-c.org/ns/1.0" schemaLocation="document.xsd"/>
<xs:attribute name="id" type="xs:ID">
<xs:annotation>
<xs:documentation>(identifier) provides a unique identifier for the element bearing the attribute.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="lang">
<xs:simpleType>
<xs:union memberTypes="xs:language">
<xs:simpleType>
<xs:restriction base="xs:token">
<xs:enumeration value="">
<xs:annotation>
<xs:documentation/>
</xs:annotation>
</xs:enumeration>
</xs:restriction>
</xs:simpleType>
</xs:union>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="base">
<xs:annotation>
<xs:documentation>provides a base URI reference with which applications can resolve relative URI references into absolute URI references.</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:anyURI">
<xs:pattern value="\S+"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="space">
<xs:annotation>
<xs:documentation>signals an intention about how white space should be managed by applications.</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:token">
<xs:enumeration value="default">
<xs:annotation>
<xs:documentation>signals that the application's default white-space processing modes are acceptable</xs:documentation>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="preserve">
<xs:annotation>
<xs:documentation>indicates the intent that applications preserve all white space</xs:documentation>
</xs:annotation>
</xs:enumeration>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:schema>
name: Reference
description: Reference
id: https://w3id.org/Reference
imports:
- linkml:types
prefixes:
linkml: https://w3id.org/linkml/
Reference: https://w3id.org/Reference
default_prefix: Reference
slots:
citation-number:
examples:
- value: '78'
range: integer
author:
examples:
- value: Lesbian and Gay Rights Service
range: string
title:
examples:
- value: The Bride Wore Pink; Legal Recognition of Our Relationships
range: string
container-title:
examples:
- value: Equity, Fiduciaries and Trusts
range: string
editor:
examples:
- value: T.G. Youdan
range: string
date:
examples:
- value: '1994'
range: integer
journal:
examples:
- value: The Age
range: string
backref:
examples:
- value: Above, n. 30
range: string
legal-ref:
examples:
- value: Dean v. District of Columbia 653 U.S. App. D.C
range: string
classes:
Reference:
slots:
- citation-number
- author
- title
- container-title
- editor
- date
- journal
- backref
- legal-ref
tree_root: true
unique_keys:
title_key:
unique_key_name: title_key
unique_key_slots:
- title
container-title_key:
unique_key_name: container-title_key
unique_key_slots:
- container-title
editor_key:
unique_key_name: editor_key
unique_key_slots:
- editor
legal-ref_key:
unique_key_name: legal-ref_key
unique_key_slots:
- legal-ref
name: Reference
description: Reference
id: https://w3id.org/Reference
imports:
- linkml:types
prefixes:
linkml: https://w3id.org/linkml/
Reference: https://w3id.org/Reference
default_prefix: Reference
slots:
citation-number:
examples:
- value: '57'
range: float
author:
examples:
- value: G. Steiner
range: string
title:
examples:
- value: 'Errata: An Examined Life'
range: string
container-title:
examples:
- value: Pressing Problems in the Law
range: string
editor:
examples:
- value: P. Birks
range: string
date:
examples:
- value: '1997'
range: integer
journal:
examples:
- value: The Law Teacher
range: string
backref:
examples:
- value: op. cit., n. 12
range: string
legal-ref:
examples:
- value: Cmnd. 2154
range: string
classes:
Reference:
slots:
- citation-number
- author
- title
- container-title
- editor
- date
- journal
- backref
- legal-ref
tree_root: true
unique_keys:
title_key:
unique_key_name: title_key
unique_key_slots:
- title
container-title_key:
unique_key_name: container-title_key
unique_key_slots:
- container-title
legal-ref_key:
unique_key_name: legal-ref_key
unique_key_slots:
- legal-ref
name: Reference
description: Reference
id: https://w3id.org/Reference
imports:
- linkml:types
prefixes:
linkml: https://w3id.org/linkml/
Reference: https://w3id.org/Reference
default_prefix: Reference
slots:
citation-number:
examples:
- value: '36'
range: integer
author:
examples:
- value: Wanner, Craig
range: string
date:
examples:
- value: '1975'
range: integer
title:
examples:
- value: The Public Ordering of Private Cases; Winning Civil Court Cases
range: string
backref:
examples:
- value: Ebenda
range: string
journal:
examples:
- value: Law and Society Review
range: string
editor:
examples:
- value: "Vereigung f\xFCr Rechtssoziologie"
range: string
container-title:
examples:
- value: Arbeitslosigkeit und Recht
range: string
classes:
Reference:
slots:
- citation-number
- author
- date
- title
- backref
- journal
- editor
- container-title
tree_root: true
unique_keys:
backref_key:
unique_key_name: backref_key
unique_key_slots:
- backref
name: Reference
description: Reference
id: https://w3id.org/Reference
imports:
- linkml:types
prefixes:
linkml: https://w3id.org/linkml/
Reference: https://w3id.org/Reference
default_prefix: Reference
slots:
editor:
examples:
- value: "Kulcs\xE1r"
range: string
title:
examples:
- value: "Recht und Konflikt \u2014 Mexiko und Afrika"
range: string
date:
examples:
- value: '1979'
range: integer
author:
examples:
- value: Siehe Bryde
range: string
citation-number:
examples:
- value: '78'
range: integer
journal:
examples:
- value: Verfassung und Recht in Obersee
range: string
container-title:
examples:
- value: "Festschrift f\xFCr Schmitthoff"
range: string
backref:
examples:
- value: oben N. 52
range: string
classes:
Reference:
slots:
- editor
- title
- date
- author
- citation-number
- journal
- container-title
- backref
tree_root: true
unique_keys:
title_key:
unique_key_name: title_key
unique_key_slots:
- title
name: Reference
description: Reference
id: https://w3id.org/Reference
imports:
- linkml:types
prefixes:
linkml: https://w3id.org/linkml/
Reference: https://w3id.org/Reference
default_prefix: Reference
slots:
citation-number:
examples:
- value: '57'
range: string
description: The number of the footnote in which a reference occurs or the number
of the reference in the Vancouver citation system
author:
examples:
- value: G. Steiner
range: string
description: The full name names of the authors or creators of a work
title:
examples:
- value: 'Errata: An Examined Life'
range: string
description: The title of a work
container-title:
examples:
- value: Pressing Problems in the Law
range: string
description: The name of the work in which the referenced work is contained, such
as an edited volume
editor:
examples:
- value: P. Birks
range: string
description: The names of the editors of a work containing other works
date:
examples:
- value: '1997'
range: string
description: The date of the publication of the work, usually the year
journal:
examples:
- value: The Law Teacher
range: string
description: The name of the journal in which the work is published
backref:
examples:
- value: op. cit., n. 12
range: string
description: A string containing a reference to a previous citation or footnote,
which is the source of the actual reference data
legal-ref:
examples:
- value: Cmnd. 2154
range: string
description: A legal reference, such as the name or identifier of a court decision
or law, sometimes including the source where this reference can be found
classes:
Reference:
slots:
- citation-number
- author
- title
- container-title
- editor
- date
- journal
- backref
- legal-ref
tree_root: true
unique_keys:
title_key:
unique_key_name: title_key
unique_key_slots:
- title
container-title_key:
unique_key_name: container-title_key
unique_key_slots:
- container-title
legal-ref_key:
unique_key_name: legal-ref_key
unique_key_slots:
- legal-ref
......@@ -56,9 +56,6 @@ class HedgedocSyncClient(HedgedocClient):
updatetime = None
def __init__(self, basel_url, doc_id=None, verbose = False):
if not doc_id:
raise ValueError("A HedgeDoc document id is required")
self.cache_dir = user_cache_dir('hedgedoc-sync-local')
self.doc_id = doc_id
self.doc_file = os.path.join(self.cache_dir, f'{self.doc_id}.md')
......@@ -129,14 +126,10 @@ class HedgedocSyncClient(HedgedocClient):
self.doc = markdown
with open(self.doc_file, 'w', encoding='utf-8') as f:
f.write(self.doc)
if self.verbose:
print(f"Updated document for {self.odc_id}")
def save_metadata(self):
with open(self.meta_file, 'w', encoding='utf-8') as f:
json.dump(self.meta_data, f)
if self.verbose:
print(f'Updated metadata for {self.meta_doc_id}.')
def update_from(self, other):
......@@ -168,7 +161,8 @@ class HedgedocSyncClient(HedgedocClient):
# save the copy and the updated metadata
self.save_doc(markdown)
self.update_metadata()
self.save_metadata()
return self.doc_id
def main():
......@@ -177,36 +171,32 @@ def main():
# Add arguments to the parser
parser.add_argument('command', help='The command to execute: checkout, checkin')
parser.add_argument('source_url', help='URL of the source document.')
parser.add_argument('target_url', help='URL of the target document. If a domain name without a path, a new document will be created.')
#parser.add_argument('-i', '--interval', type=int, default=10, help='The time interval in which the documents should be synchronized, in seconds. Default is 10 seconds.')
parser.add_argument('-v', '--verbose', action='store_true', help='Provide verbose output.')
parser.add_argument('-s', '--local-server-url', default='http://localhost:3000', help='The URL of the local HedgeDoc server.')
# Parse the arguments
args = parser.parse_args()
source_base_url, source_id = parse_url(args.source_url)
target_base_url, target_id = parse_url(args.target_url)
source_base_url, source_doc_id = parse_url(args.source_url)
target_base_url = args.local_server_url
verbose = args.verbose
# create the clients
source = HedgedocSyncClient(source_base_url, source_id, verbose=verbose)
target = HedgedocSyncClient(target_base_url, target_id, verbose=verbose)
source = HedgedocSyncClient(source_base_url, source_doc_id, verbose=verbose)
target_doc_id = source.meta_data.get('target_doc_id', None)
target = HedgedocSyncClient(target_base_url, target_doc_id, verbose=verbose)
# handle the commands
if args.command == "checkout":
target.update_from(source)
target_doc_id = target.update_from(source)
source.meta_data['target_doc_id'] = target_doc_id
source.save_metadata()
print(f'Document has been checked out from {source.document_url()} to {target.document_url()}')
elif args.command == "checkin":
if target_doc_id is None:
print("Cannot check in, no target doc id is set")
exit(1)
source.update_from(target)
print(f'Document has been checked in from {target.document_url()} to {source.document_url()}')
elif args.command == "compare":
s, t = source.last_update_time(), target.last_update_time()
if s > t:
print(f'{source.document_url()} is newer')
elif t > s:
print(f'{target.document_url()} is newer')
else:
# this will never be called
print('Documents are identical')
if __name__ == "__main__":
main()
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment