The goal of retirementDash
is to present pertinent and relevant criteria for selecting a retirement location in the United States. This project proceeded in two stages. The first stage was to create a county-level dataset retirementData
, which is hosted in its own package and repository. The second stage was to display the data in an interactive, user-friendly dashboard, shown above.
You can install the development and experimental version of retirementDash
from its repository with:
# Or the development version from GitHub:
# install.packages("devtools")
install_github("RobWiederstein/retirementDash")
The side panel provides 17 criteria to filter the 3,142 United States counties. The sliders were preset to the 2.5% and the 97.5% percentiles to eliminate outliers. With seventeen sliders set in a similar manner, only 2028 counties display when the select counties
button is pushed.
The map contains an overlay for airports, colleges, hospitals and military bases. For those features to be displayed, the adjacent box must be checked. Airports include information regarding annual passengers; colleges the number of students; hospitals the CMS star rating; and military bases the surface area.
The counties tab displays the filtered results in a tabular form. The user may select variables and sort and download the counties that meet his or her criteria. This is particularly useful for preserving the results.
The user may use the x-axis
and y-axis
axis to create a scatterplot. Additional attributes for size and color are provided. This could be helpful in further refining the criteria on the landing page. For example, some parts of the United States have very high housing prices relative to household income, a variable named years_to_payoff
. Users may then reset the inputs based upon the analyzer plot.
The following packages were indispensable to the retirementData
and retirementDash
projects:
Please note that the retirementDash project is released with a Contributor Code of Conduct. By contributing to this project, you agree to abide by its terms.


The giant panda, also known as the panda bear or simply the panda, is a bear native to south central China. It is characterised by large, black patches around its eyes, over the ears, and across its round body.
The name "giant panda" is sometimes used to distinguish it from the red panda, a neighboring musteloid.


Privacy policy
1. Introduction
1.1 We are committed to safeguarding the privacy of our website visitors; in this policy we explain how we will treat your personal information.
1.2 [We will ask you to consent to our use of cookies in accordance with the terms of this policy when you first visit our website.] OR [By using our website and agreeing to this policy, you consent to our use of cookies in accordance with the terms of this policy.]
2. Credit
2.1 This document was created using a template from SEQ Legal (https://www.p2ptraders.com).
3. Collecting personal information
3.1 We may collect, store and use the following kinds of personal information:
(a) [information about your computer and about your visits to and use of this website (including [your IP address, geographical location, browser type and version, operating system, referral source, length of visit, page views and website navigation paths])];
(b) [information that you provide to us when registering with our website (including [your email address])];
(c) [information that you provide when completing your profile on our website (including [your name, profile pictures, gender, date of birth, relationship status, interests and hobbies, educational details and employment details])];
(d) [information that you provide to us for the purpose of subscribing to our email notifications and/or newsletters (including [your name and email address])];
(e) [information that you provide to us when using the services on our website, or that is generated in the course of the use of those services (including [the timing, frequency and pattern of service use])];
(f) [information relating to any purchases you make of our [goods] OR [services] OR [goods and/or services] or any other transactions that you enter into through our website (including [your name, address, telephone number, email address and card details])];
(g) [information that you post to our website for publication on the internet (including [your user name, your profile pictures and the content of your posts])];
(h) [information contained in or relating to any communication that you send to us or send through our website (including [the communication content and metadata associated with the communication])]; and
(i) [any other personal information that you choose to send to us].
[additional list items]
3.2 Before you disclose to us the personal information of another person, you must obtain that person's consent to both the disclosure and the processing of that personal information in accordance with this policy.
4. Using personal information
4.1 Personal information submitted to us through our website will be used for the purposes specified in this policy or on the relevant pages of the website.
4.2 We may use your personal information to:
(a) [administer our website and business];
(b) [personalise our website for you];
(c) [enable your use of the services available on our website];
(d) [send you goods purchased through our website];
(e) [supply to you services purchased through our website];
(f) [send statements, invoices and payment reminders to you, and collect payments from you];
(g) [send you non-marketing commercial communications];
(h) [send you email notifications that you have specifically requested];
(i) [send you our email newsletter, if you have requested it (you can inform us at any time if you no longer require the newsletter)];
(j) [send you marketing communications relating to our business [or the businesses of carefully-selected third parties] which we think may be of interest to you, by post or, where you have specifically agreed to this, by email or similar technology (you can inform us at any time if you no longer require marketing communications)];
(k) [provide third parties with statistical information about our users (but those third parties will not be able to identify any individual user from that information)];
(l) [deal with enquiries and complaints made by or about you relating to our website];
(m) [keep our website secure and prevent fraud]; and
(n) [verify compliance with the terms and conditions governing the use of our website [(including monitoring private messages sent through our website private messaging service)]].
[additional list items]
4.3 If you submit personal information for publication on our website, we will publish and otherwise use that information in accordance with the licence you grant to us.
4.4 Your privacy settings can be used to limit the publication of your information on our website, and can be adjusted using privacy controls on the website.
4.5 We will not, without your express consent, supply your personal information to any third party for the purpose of their or any other third party's direct marketing.
4.6 All our website financial transactions are handled through our payment services provider, [PSP name]. You can review the provider's privacy policy at [URL]. We will share information with our payment services provider only to the extent necessary for the purposes of processing payments you make via our website, refunding such payments and dealing with complaints and queries relating to such payments and refunds.
5. Disclosing personal information
5.1 We may disclose your personal information to [any of our employees, officers, insurers, professional advisers, agents, suppliers or subcontractors] insofar as reasonably necessary for the purposes set out in this policy.
5.2 We may disclose your personal information to any member of our group of companies (this means our subsidiaries, our ultimate holding company and all its subsidiaries) insofar as reasonably necessary for the purposes set out in this policy.
5.3 We may disclose your personal information:
(a) to the extent that we are required to do so by law;
(b) in connection with any ongoing or prospective legal proceedings;
(c) in order to establish, exercise or defend our legal rights (including providing information to others for the purposes of fraud prevention and reducing credit risk);
(d) [to the purchaser (or prospective purchaser) of any business or asset that we are (or are contemplating) selling]; and
(e) [to any person who we reasonably believe may apply to a court or other competent authority for disclosure of that personal information where, in our reasonable opinion, such court or authority would be reasonably likely to order disclosure of that personal information].
5.4 Except as provided in this policy, we will not provide your personal information to third parties.
6. International data transfers
6.1 Information that we collect may be stored and processed in and transferred between any of the countries in which we operate in order to enable us to use the information in accordance with this policy.
6.2 Information that we collect may be transferred to the following countries which do not have data protection laws equivalent to those in force in the European Economic Area: [the United States of America, Russia, Japan, China and India].
6.3 Personal information that you publish on our website or submit for publication on our website may be available, via the internet, around the world. We cannot prevent the use or misuse of such information by others.
6.4 You expressly agree to the transfers of personal information described in this Section 6.
7. Retaining personal information
7.1 This Section 7 sets out our data retention policies and procedure, which are designed to help ensure that we comply with our legal obligations in relation to the retention and deletion of personal information.
7.2 Personal information that we process for any purpose or purposes shall not be kept for longer than is necessary for that purpose or those purposes.
7.3 Without prejudice to Section 7.2, we will usually delete personal data falling within the categories set out below at the date/time set out below:
(a) [personal data type] will be deleted [date/time].
[additional list items]
7.4 Notwithstanding the other provisions of this Section 7, we will retain documents (including electronic documents) containing personal data:
(a) to the extent that we are required to do so by law;
(b) if we believe that the documents may be relevant to any ongoing or prospective legal proceedings; and
(c) in order to establish, exercise or defend our legal rights (including providing information to others for the purposes of fraud prevention and reducing credit risk).
8. Security of personal information
8.1 We will take reasonable technical and organisational precautions to prevent the loss, misuse or alteration of your personal information.
8.2 We will store all the personal information you provide on our secure (password- and firewall-protected) servers.
8.3 All electronic financial transactions entered into through our website will be protected by encryption technology.
8.4 You acknowledge that the transmission of information over the internet is inherently insecure, and we cannot guarantee the security of data sent over the internet.
8.5 You are responsible for keeping the password you use for accessing our website confidential; we will not ask you for your password (except when you log in to our website).
9. Amendments
9.1 We may update this policy from time to time by publishing a new version on our website.
9.2 You should check this page occasionally to ensure you are happy with any changes to this policy.
9.3 We may notify you of changes to this policy [by email or through the private messaging system on our website].
10. Your rights
10.1 You may instruct us to provide you with any personal information we hold about you; provision of such information will be subject to:
(a) the payment of a fee (currently fixed at GBP 10); and
(b) the supply of appropriate evidence of your identity [(for this purpose, we will usually accept a photocopy of your passport certified by a solicitor or bank plus an original copy of a utility bill showing your current address)].
10.2 We may withhold personal information that you request to the extent permitted by law.
10.3 You may instruct us at any time not to process your personal information for marketing purposes.
10.4 In practice, you will usually either expressly agree in advance to our use of your personal information for marketing purposes, or we will provide you with an opportunity to opt out of the use of your personal information for marketing purposes.
11. Third party websites
11.1 Our website includes hyperlinks to, and details of, third party websites.
11.2 We have no control over, and are not responsible for, the privacy policies and practices of third parties.
12. Updating information
12.1 Please let us know if the personal information that we hold about you needs to be corrected or updated.
13. Cookies
13.1 Our website uses cookies.
13.2 A cookie is a file containing an identifier (a string of letters and numbers) that is sent by a web server to a web browser and is stored by the browser. The identifier is then sent back to the server each time the browser requests a page from the server.
13.3 Cookies may be either "persistent" cookies or "session" cookies: a persistent cookie will be stored by a web browser and will remain valid until its set expiry date, unless deleted by the user before the expiry date; a session cookie, on the other hand, will expire at the end of the user session, when the web browser is closed.
13.4 Cookies do not typically contain any information that personally identifies a user, but personal information that we store about you may be linked to the information stored in and obtained from cookies.
13.5 We use [only session cookies] OR [only persistent cookies] OR [both session and persistent cookies] on our website.
13.6 The names of the cookies that we use on our website, and the purposes for which they are used, are set out below:
(a) we use [cookie name] to [recognise a computer when a user visits our website] OR [track users as they navigate the website] OR [enable the use of a shopping cart on the website] OR [improve the website's usability] OR [administer the website] OR [prevent fraud and improve the security of the website] OR [personalise the website for each user] OR [target advertisements which may be of particular interest to specific users] OR [validate authenticated users sessions] OR [facilitate the use of our website search engine] OR [[specify purpose]].
[additional list items]
13.7 Most browsers allow you to refuse to accept cookies; for example:
(a) in Internet Explorer (version 11) you can block cookies using the cookie handling override settings available by clicking "Tools", "Internet Options", "Privacy" and then "Advanced";
(b) in Firefox (version 47) you can block all cookies by clicking "Tools", "Options", "Privacy", selecting "Use custom settings for history" from the drop-down menu, and unticking "Accept cookies from sites"; and
(c) in Chrome (version 52), you can block all cookies by accessing the "Customise and control" menu, and clicking "Settings", "Show advanced settings" and "Content settings", and then selecting "Block sites from setting any data" under the "Cookies" heading.
13.8 Blocking all cookies will have a negative impact upon the usability of many websites.
13.9 If you block cookies, you will not be able to use all the features on our website.
13.10 You can delete cookies already stored on your computer; for example:
(a) in Internet Explorer (version 11), you must manually delete cookie files (you can find instructions for doing so at http://windows.microsoft.com/en-gb/internet-explorer/delete-manage-cookies#ie=ie-11);
(b) in Firefox (version 47), you can delete cookies by clicking "Tools", "Options" and "Privacy", then selecting "Use custom settings for history" from the drop-down menu, clicking "Show Cookies", and then clicking "Remove All Cookies"; and
(c) in Chrome (version 52), you can delete all cookies by accessing the "Customise and control" menu, and clicking "Settings", "Show advanced settings" and "Clear browsing data", and then selecting "Cookies and other site and plug-in data" before clicking "Clear browsing data".
13.11 Deleting cookies will have a negative impact on the usability of many websites.
14. Data protection registration
14.1 We are registered as a data controller with the UK Information Commissioner's Office.
14.2 Our data protection registration number is [number].
15. Our details
15.1 This website is owned and operated by [name].
15.2 We are registered in [England and Wales] under registration number [number], and our registered office is at [address].
15.3 Our principal place of business is at [address].
15.4 You can contact us:
(a) [by post, using the postal address [given above]];
(b) [using our website contact form];
(c) [by telephone, on [the contact number published on our website from time to time]]; or
(d) [by email, using [the email address published on our website from time to time]].
[additional list items]
Free privacy policy:
drafting notes
A standard website privacy policy, which will help you to comply with UK data protection legislation. This policy covers the following matters (amongst others): the collection of personal information; the use of that personal information; disclosures of that personal information to third parties; the security of that personal information; and the use of cookies on the website. This document might not be suitable for you if the ways in which you use personal information are complex or unusual.
Section 1: Introduction
Section 1.1
"Personal information": for day-to-day purposes, it is best to assume that all information which relates to a living individual constitutes personal information.
Section 1.2
Optional element.
The inclusion of this statement in your privacy policy will not in itself satisfy the requirements of the Privacy and Electronic Communications (EC Directive) Regulations 2003 as regards consent to the use of cookies. Guidance concerning methods of obtaining such consent is included on the Information Commissioner's website (http://www.ico.gov.uk).
· How will you gain users' consent to the use of cookies?
Section 2: Credit
Section: Free
documents licensing warning
Optional element. Although you need to retain the credit, you should remove the inline copyright warning from this document before use.
Section 3: Collecting personal information
Section 3.1
· What types of personal information will or might the website operator collect?
· What analytics data will you collect?
· What information will be collected from users who register with the website?
· What profile information is collected through the website?
· What information will be collected from users who subscribe to website services, email notifications and/or newsletters?
· What information is processed in connection with the provision of website services?
· What can be purchased through the website: goods, services or both?
· What transactional data will be collected from users?
· What personal information can a user publish through the website?
· What communications information may be collected?
Section 3.2
Optional element.
Section 4: Using personal information
Section 4.2
You must list here the uses to which you will (or may in future) put personal data. We have suggested some common categories. As a general rule, where you plan to use personal information you have collected for the purpose of direct marketing, this should be made clear on the page where the information is collected, and you should ensure that this only happens if users opt in to the marketing (eg "Click here if you would like us to send you information by email about products which we think will interest you."). There are, however, exceptions to this general rule. There are also rules about the content of direct marketing communications. If you are in any doubt about complying with your legal obligations in relation to direct marketing, you should seek professional advice.
· For what purposes will the website operator use personal information collected through the website?
· Might marketing communications relate to third party businesses?
· Will private messages sent by users be monitored to ensure compliance with website terms and conditions?
Section 4.3
Optional element. Will users have the opportunity to publish any personal information on the website?
Section 4.4
Optional element.
Section 4.5
Optional element. Will the website undertake in this document not to supply any user's personal information to a third party for the purpose of third party direct marketing?
Section 4.6
Optional element. Will the website operator pass any personal information to any third party payment services provider?
· What is the name of the payment services provider that processes website transactions?
· At what web address can the privacy policy of the payment services provider be found?
Section 5: Disclosing personal information
Section 5.1
· To which categories of person may personal information collected through the website be disclosed?
Section 5.2
Optional element. Is the website operator part of a group of companies in circumstance where one or more of those other group companies might need access to personal information collected by reference to this document?
Section 5.3
A website operator may be obliged to disclose personal data to a third party under various laws. For example, under the Defamation Act 2013 and the Defamation (Operators of Websites) Regulations 2013, a website operator may be required to pass personal data between a complainant and a poster - i.e. a person who posts on the website material which may be defamatory of the claimant.
· Does the website operator need a right to disclose personal data to business purchasers and potential business purchasers?
· Does the website operator require a right to disclose personal data in anticipation of a court judgment or regulatory action?
Section 6: International data transfers
Does the website operator, or might the website operator, transfer or have transferred outside the European Economic Area (EEA) any personal information that it controls?
Give as much detail as possible about any such international transfers. You need to be aware that the inclusion of this provision will not be sufficient to ensure that all international transfers of personal data are lawful. If in doubt, you should seek professional advice on this point.
Section 6.2
Optional element. Will any personal data be transferred outside the EEA?
· To which countries outside the EEA may personal data be transferred?
Section 6.3
Optional element. Will users have the opportunity to publish personal information on the website?
Section 6.4
This consent statement is unlikely to create an effective consent to extra-EEA transfers on its own.
Section 7: Retaining personal information
Section 7.1
Optional element.
Section 7.3
Optional element. Does the website operator have any specific policies in place regarding time periods for the deletion of personal data?
· Does the website operator have any specific policies in place regarding time periods for the deletion of personal data?
Section 8: Security of personal information
Section 8.2
Optional element.
There is an obligation upon data controllers to store personal data securely.
Section 8.3
Optional element.
Section 8.4
Optional element.
Section 8.5
Optional element.
Section 9: Amendments
Section 9.2
Optional element.
Section 9.3
Optional element. Will you ever contact users to notify them of changes to the document?
· How will users be notified of changes to the document?
Section 10: Your rights
Section 10.1
· What evidence of identity will you require before fulfilling a data protection subject access request?
Section 10.4
Optional element.
Section 11: Third party websites
Optional element.
Section 12: Updating information
Optional element.
Section 13: Cookies
Optional element.
Section 13.4
Optional element.
Section 13.5
· What types of cookies will be used on the website?
Section 13.6
· Details of cookie used on the website should be provided here.
· Identify the cookie by name.
Section 13.9
Optional element. Will the blocking of cookies have a negative effect upon the use of the website from a user perspective?
Section 14: Data protection registration
Optional element.
Section 14.2
· What is the website operator's data protection registration number?
Section 15: Our details
Optional element.
UK companies must provide their corporate names, their registration numbers, their place of registration and their registered office address on their websites (although not necessarily in this document). Sole traders and partnerships that carry on a business in the UK under a "business name" (i.e. a name which is not the name of the trader/names of the partners or certain other specified classes of name) must also make certain website disclosures: (i) in the case of a sole trader, the individual's name; (ii) in the case of a partnership, the name of each member of the partnership; and (iii) in either case, in relation to each person named, an address in the UK at which service of any document relating in any way to the business will be effective. All websites covered by the Electronic Commerce (EC Directive) Regulations 2002 must provide a geographic address (not a PO Box number) and an email address. All website operators covered by the Provision of Services Regulations 2009 must also provide a telephone number.
Section 15.1
· What is the name of the company, partnership, individual or other legal person or entity that owns and operates the website?
Section 15.2
Optional element. Is the relevant person a company?
· In what jurisdiction is the company registered?
· What is the company's registration number or equivalent?
· Where is the company's registered address?
Section 15.3
Optional element.
· Where is the relevant person's head office or principal place of business?
Section 15.4
Optional element.
· By what means may the relevant person be contacted?
· Where is the relevant person's postal address published?
· Either specify a telephone number or give details of where the relevant number may be found.
· Either specify an email address or give details of where the relevant email address may be found.


# (c) 2012-2014, Michael DeHaan<EMAIL_ADDRESS>#
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
# Make coding more python3-ish
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
from yaml.constructor import Constructor, ConstructorError
from yaml.nodes import MappingNode
from ansible.parsing.yaml.objects import AnsibleMapping, AnsibleSequence, AnsibleUnicode
from ansible.vars.unsafe_proxy import wrap_var
try:
from __main__ import display
except ImportError:
from ansible.utils.display import Display
display = Display()
[docs]class AnsibleConstructor(Constructor):
def __init__(self, file_name=None):
self._ansible_file_name = file_name
super(AnsibleConstructor, self).__init__()
[docs] def construct_yaml_map(self, node):
data = AnsibleMapping()
yield data
value = self.construct_mapping(node)
data.update(value)
data.ansible_pos = self._node_position_info(node)
[docs] def construct_mapping(self, node, deep=False):
# Most of this is from yaml.constructor.SafeConstructor. We replicate
# it here so that we can warn users when they have duplicate dict keys
# (pyyaml silently allows overwriting keys)
if not isinstance(node, MappingNode):
raise ConstructorError(None, None,
"expected a mapping node, but found %s" % node.id,
node.start_mark)
self.flatten_mapping(node)
mapping = AnsibleMapping()
# Add our extra information to the returned value
mapping.ansible_pos = self._node_position_info(node)
for key_node, value_node in node.value:
key = self.construct_object(key_node, deep=deep)
try:
hash(key)
except TypeError as exc:
raise ConstructorError("while constructing a mapping", node.start_mark,
"found unacceptable key (%s)" % exc, key_node.start_mark)
if key in mapping:
display.warning(u'While constructing a mapping from {1}, line {2}, column {3}, found a duplicate dict key ({0}). Using last defined value only.'.format(key, *mapping.ansible_pos))
value = self.construct_object(value_node, deep=deep)
mapping[key] = value
return mapping
[docs] def construct_yaml_str(self, node, unsafe=False):
# Override the default string handling function
# to always return unicode objects
value = self.construct_scalar(node)
ret = AnsibleUnicode(value)
ret.ansible_pos = self._node_position_info(node)
if unsafe:
ret = wrap_var(ret)
return ret
[docs] def construct_yaml_seq(self, node):
data = AnsibleSequence()
yield data
data.extend(self.construct_sequence(node))
data.ansible_pos = self._node_position_info(node)
[docs] def construct_yaml_unsafe(self, node):
return self.construct_yaml_str(node, unsafe=True)
def _node_position_info(self, node):
# the line number where the previous token has ended (plus empty lines)
# Add one so that the first line is line 1 rather than line 0
column = node.start_mark.column + 1
line = node.start_mark.line + 1
# in some cases, we may have pre-read the data and then
# passed it to the load() call for YAML, in which case we
# want to override the default datasource (which would be
# '<string>') to the actual filename we read in
datasource = self._ansible_file_name or node.start_mark.name
return (datasource, line, column)
AnsibleConstructor.add_constructor(
u'tag:yaml.org,2002:map',
AnsibleConstructor.construct_yaml_map)
AnsibleConstructor.add_constructor(
u'tag:yaml.org,2002:python/dict',
AnsibleConstructor.construct_yaml_map)
AnsibleConstructor.add_constructor(
u'tag:yaml.org,2002:str',
AnsibleConstructor.construct_yaml_str)
AnsibleConstructor.add_constructor(
u'tag:yaml.org,2002:python/unicode',
AnsibleConstructor.construct_yaml_str)
AnsibleConstructor.add_constructor(
u'tag:yaml.org,2002:seq',
AnsibleConstructor.construct_yaml_seq)
AnsibleConstructor.add_constructor(
u'!unsafe',
AnsibleConstructor.construct_yaml_unsafe)


I am an interdisciplinary researcher and intergrated designer across academia and industry with decades of experience in scientific design research methods, design process, and interactive media storytelling. I conducted various experience design and research projects in Samsung Electronics, Art Center NABi, and SK Telecom for next-generation products and services by envisioning scenarios, innovative product design prototypes, usability/user testing, strategic plans, and design process modeling and management.
Design, in my perspective, is a decision-making process for positive changes in human well-being. We stand as designers who are responsible for the world with the artifacts we’ve made, as well as decision-makers who can introduce creative solutions that can help other people for better choices. For better decision-making, designers should understand humans in terms of perception, cognition, emotion, judgment, and interplay within them. Designers need to have a scientific mind: observation, pattern-finding, modeling, and evaluation with feedback in order to predict the effect of the designs. We can expand the understanding of design through theories and methods from humane studies.
I’m currently an independent design researcher and expanding my research area to Digital Humanities for Art/Design History, Aesthetics, and Psychology. I taught Cognitive/Social Psychology, Visual/Interaction/Experience Design, Non-Linear Interactive Storytelling, and Creative Coding at the academic institutions including Yonsei University, the University of Michigan, Northern Kentucky University, the University of Cincinnati, and currently teaching at UCLA. Since 2020, I co-founded HUE Project (Humans in User Experience) and serve as an advisor and principal project manager to advocate human-centered design and research. Please feel free to contact me [ sookie at g dot ucla dot edu ] or [ HUE ] for project collaboration.


PASSIONE D'AMORE A film review by James Berardinelli Copyright 1994 James Berardinelli
RATING (0 TO 10): 6.3
Year Released: 1981 Re-release: Fall 1994 Running Length: 1:56 Rated: No MPAA Rating (Sex, nudity, violence)
Starring: Bernard Giraudeau, Massimo Girotti, Jean-Louis Trintignant, Laura Antonelli Director: Ettore Scola Screenplay: Ettore Scola Cinematography: Claudio Rogoni Released by Kino International In Italian with subtitles
1994 has offered an opportunity for American viewers to catch a snapshot of the career of the well-respected European actor Jean-Louis Trintignant. Earlier this year, with the re-release of Bernardo Bertolucci's THE CONFORMIST, the (relatively) youthful Trintignant was featured in an early leading role. In the final installment of Krzysztof Kieslowski's THREE COLORS trilogy, RED, a more grizzled Trintignant, twenty-four years older, appears opposite Irene Jacob. Now, with the second theatrical engagement for Ettore Scola's 1981 PASSIONE D'AMORE (resurrected because of the success of Steven Sondheim's Tony-winning musical PASSION, which is based on this film), we get a performance chronologically midway between the other movies.
Actually, as far as acting goes, Trintignant's performance is one of the high points of PASSIONE D'AMORE. Controlled and quietly passionate, the actor never overplays his role--a qualification that cannot be applied to his two co-stars, Bernard Giraudeau and Massimo Girotti. Ettore Scola's film contains a number of good ideas, more than one of which is sabotaged by a display of histrionics.
PASSIONE D'AMORE is essentially a "Beauty and the Beast" story with a twist. Set in 1862 Italy, Scola's film examines familiar themes from a different perspective. This time, it's the man, Giorgio (Giraudeau), who is the specimen of physical perfection. He becomes the object of an obsessive and unhealthy attraction developed by Fosca (Girotti), the homely daughter of Giorgio's commanding officer in the Italian army. As repulsed as he is by her appearance, Giorgio nevertheless attempts to befriend the ailing Fosca, but inadvertently becomes trapped in an unwanted relationship when the woman's doctor (Trintignant) informs him that without his attention, Fosca will die. This situation not only threatens Giorgio's own health, but drives a wedge into his relationship with his alluring lover, Clara (Laura Antonelli).
Of course, the major theme is that, ultimately, there isn't necessarily a connection between physical appearance and love. The affair between the comely pair of Giorgio and Clara proves fragile while the feelings binding the protagonist to Fosca, although taking time to develop, are both deeper and more lasting. Actually, Giorgio is the only one to acknowledge this truth. Even Fosca, desperately longing for affection, doesn't see it, observing that it's impossible to love someone as ugly as she is.
A secondary issue dealt with by PASSIONE D'AMORE, and the one that sets it apart from most similar films, is the potentially-devastating nature of any passionate relationship. Love is more often presented as a destructive force than something positive, with the corrosive effects of obsession used as a prime example. It's never clear whether the change in Giorgio's attitude to Fosca is caused by an inner revelation or is the result of her unremitting, slavish adoration eventually eroding his defenses and sanity.
Combine these two themes, and there's fertile territory for a powerful motion picture. Unfortunately, PASSIONE D'AMORE too frequently crosses the line separating thoughtful production from overacted melodrama, thus at times eviscerating its potential impact. Girotti's displays of emotion aren't always appropriate and Giraudeau fails to display the range demanded by his character, the only one to really undergo a transformation. Despite these acting deficiencies, the story is strong enough to be disturbing, and worth seeing by all who don't demand a Disney-like ending to every version of this age-old tale.
The above represents the opinions of the author, and not necessarily those of Bellcore or any organization within Bellcore.
- James Berardinelli<EMAIL_ADDRESS>.
The review above was posted to the
rec.arts.movies.reviews newsgroup (de.rec.film.kritiken for German reviews).
The Internet Movie Database accepts no responsibility for the contents of the
review and has no editorial control. Unless stated otherwise, the copyright
belongs to the author.
Please direct comments/criticisms of the review to relevant newsgroups.
Broken URLs inthe reviews are the responsibility of the author.
The formatting of the review is likely to differ from the original due
to ASCII to HTML conversion.
Related links: index of all rec.arts.movies.reviews reviews


Test Page - Making Sure it Works
This is a sample guide designed to test:
- Proper translation of +something+ to something
- Automatic heading numbering
- Generation of Table of Contents
- Code blocks with filenames
- Provide NOTE/INFO/WARNING shortcuts
1 - I'm the first heading!
This is the first paragraph. It's nice and short.
$ some bash code here ~ Yup...I think this worked...
Another paragraph goes here. I could type for a fairly long time and make some really long sentences and keep it going until the end of all days, but I think I shall defer until a better time. That makes much more sense.
some/one/line/code/here
Here is some more paragraph text.
1.1 - I'm a subheading.
I'm even more text.
Woah! Watch out for me.
1.1.1 - I'm a sub-subheading.
And here is some more text.
2 - I am the second heading. I'm not so great.
I'm a pretty cool note!
Woot, we got more text coming right at you!
2.1 - Another subheading.
With some more text.
I'm just here to tell you about something.
And here is some fancy code below:
/some/ruby/file.rb
a = 1 + 2
b = a / 3
c = a * b
puts a, b, c
2.1.1 - Another sub-subheading.
With even more text/code.
/i/am/some/javascript3.js{ here: { comes: "the bride", 1: "more time", "something else": [3, 'b', { fu: 'bar' }] } }
2.1.2 - Yet one more sub-subheading.
With the last bit of text.


bootstrap-input-prefix Examples
Fields with Labels
Regular Input Field
Large Input Field
Small Input Field
Fields without Labels
Inline Form
Regular Input Field
Large Input Field
Small Input Field
Horizontal Form
Regular Input Field
Large Input Field
Small Input Field
Fields with Validation States
Success Input Field
Warning Input Field
Error Input Field


--- layout: post title: Etude House Haul tags: - Comb - Cotton - Cute Pink - Dry Shampoo - Etude House - Hand Care - Hand Cream - Lip Balm - Lip Care - Mirror - Nail Polish - Oil Blotting Paper - Skin Care - Sponge status: publish type: post published: true meta: _yoast_wpseo_linkdex: '19' _edit_last: '2' _yoast_wpseo_focuskw: Etude House Haul _yoast_wpseo_title: Etude House Haul - Miss Enchanted _yoast_wpseo_metadesc: Etude House Haul _yoast_wpseo_metakeywords: '' _yoast_wpseo_meta-robots-noindex: '0' _yoast_wpseo_meta-robots-nofollow: '0' _yoast_wpseo_meta-robots-adv: none _yoast_wpseo_sitemap-include: ! '-' _yoast_wpseo_sitemap-prio: ! '-' _yoast_wpseo_canonical: '' _yoast_wpseo_redirect: '' _thumbnail_id: '7784' ---
Etude House Animal Hand Creams and Lip Balms... aren't these just too cute ?
Few cute pieces from the Princess Etoinette Collection
Dry Shampoo, Fragrant hand creams Body Wash, and cotton (Loved the coffee cup idea)
Sponge cake ... Seriously who gets these genius ideas... and Nail Polish
You can never leave a Korean shop without free samples.... Can You ?
I just can't wait to photograph and review these cuties... which ones did you like the most ?


This site demonstrates key functionality of Azure Search. For more information email the search services team or follow their blog.
Search live global Pokemon Go database and display results in Bing maps.


Privacy Policy
We know absolutely nothing about you and do not store any of your data. We don't track you. Everything you do in our extension belongs only to you and is not sent to our servers.
In all seriousness, privacy and openness are a priority for us. Our code is fully open at Github and is available for review.
What are we building?
No data is being collected at this timeDelete your data
At the moment the application works exclusively in your browser and does not send data to our servers. This way, we just delete nothing.
Browser permissions
Our extension requests two approvals:
1. Access to all visited web pages
This seems to be too broad and unsafe a right, but it is necessary.
Our extension supports several videostreaming services, including
kino.pub. This service provides a personal unique
domain for each user. Thus, we do not know exactly on what domain our extension will run. Instead, the first
thing the application does is try to determine whether this site is one of the supported services and if it is
not, it does not execute any code at all. We do not collect information about the pages you visit.
2. Access to Storage
This permission is required to store the plugin settings in your browser. For example, translation language or
subtitle display settings.
Contact us
Easysubs was created by independent developer
Petr Stepchenko
If you want to contact me with any questions, just write to
<EMAIL_ADDRESS>or Telegram


git-request-pull(1) Manual Page
NAME
git-request-pull - Generates a summary of pending changes
SYNOPSIS
git request-pull [-p] <start> <url> [<end>]
DESCRIPTION
Summarizes the changes between two commits to the standard output, and includes the given URL in the generated summary.
OPTIONS
- -p
Show patch text
- <start>
Commit to start at.
- <url>
URL to include in the summary.
- <end>
Commit to end at; defaults to HEAD.
GIT
Part of the git(1) suite


Images
Sandra Adams
<EMAIL_ADDRESS>My files
shared with me
starred
Recent
Offline
Uploads
Backups
Images
TODAY
TODAY


What This Is and How to Use It
The enchant.js Map Editor
This is a tool written in JavaScript for quickly creating maps for use with enchant.js. More specifically, since maps in enchant.js images placed in an array from a tileset, this tool is used to generate those arrays. This saves you from having to manually type out the array.
How do I use it?
To create a map using the Map Editor, do the following:
- Creating a Blank Map
- Enter in the width of your desired map in pixels.
- Enter in the height of your desired map in pixels.
- Choose your desired tileset. (Currently 'RPG' is the most complete.)
- Hit 'Create Blank Map'.
- Editing the Map
- Choose a basic background tile for your map by clicking a tile (i.e. the green grass tile), clicking 'fill,' and then clicking on the map.
- Click on 'pen,' click on a tile, and then click on the map to place the tile.
- To add features that show the background behind them (like trees), click on 'layer2,' and then add your tiles.
- To make certain tiles on the map impassable by characters, click on 'impassability' and use the Pen to designate a tile location on the map as impassable. The impassable designation can be erased with the "-1" tile.
- Regular tiles can be erased with the "-1" tile when on layer1, layer2, etc.


"QUEEN" Music Compilation
01.Queen - Bohemian Rhapsody
02.Queen - I Want to Break Free
03.Queen - Love of My Life
04.Queen - Somebody to Love
05.Queen - We Will Rock You
06.Queen - We Are the Champions
07.Queen - The Show Must Go On
5:54
4:31
3:41
5:09
2:14
3:10
4:22


Codehaus XFire
DocumentationQuicklinksDevelopers
Sponsors |
Aegis is the default XFire binding which maps XML to POJOs. It supports code first development only at this point - i.e. you write your service in POJOs and it will generate the XML schema/wsdl for you. XML and Annotation Mapping OverviewAegis has a flexible mapping system so you can control how your beans are controlled. By default your POJOs are serialized based on their name and namespaces. If you have a class in the "org.codehaus.xfire" package named "Employee" it would be serialized in namespace "http://xfire.codehaus.org" with the local name "Employee" Fore example, the java class: public class Employee { private String name; private String title; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } } In XML this translates to: <Employee xmlns="http://xfire.codehaus.org"> <name>Santa Claus</name> <title>Chief Present Officer (CPO)</title> </Employee> In XML Schema this would become a complex type: <xsd:complexType name="Employee"> <xsd:sequence> <xsd:element name="name" type="xsd:string" minOccurs="0" maxOccurs="1/> <xsd:element name="title" type="xsd:string" minOccurs="0" maxOccurs="1/> </xsd:sequence> </xsd:complexType>
Supported Types
If you have constructors defined in your Java beans, make sure a default constructor (i.e. no arguments) is also declared. (Aegis needs a no-argument contstructor to instantiate client Java classes.) Controlling Mappings with XMLIts easy to control how your service and its beans are mapped to xml. If you are using Java 5.0 skip straight down to that section otherwise read on to learn how to configure serialization via mapping files. Mapping files must exist in the same package as your bean or service class on the class path. In the above example the mapping file would be named "/org/codehaus/xfire/Employee.aegis.xml", with the following format: <mappings> <mapping uri="" name=""> <method name="methodName"> <return-type mappedName="" componentType=""/> <parameter index="" mappedName=""/> </method> <property name="" mappedName="" style="attribute|element" componentType=""/> </mapping> </mappings> When you are creating ClassName.aegis.xml files to control type mapping, you will have only one mapping element, and you don't need any attributes on the mapping element. You use property elements to specify how to map your properties. You must supply name= to select the property. There are more examples of specific cases below. Note that <method> is used to configure methods on your service and <property> is used to configure properties on your javabeans. Controlling NamingLets pretend that in the above example you would like the elements names to be capatilized and in the namespace "urn:north-pole:operations". You could achieve this through a mapping file like so: <mappings xmlns:np="urn:north-pole:operations"> <mapping name="np:Employee"> <property name="name" mappedName="Name"/> <property name="title" mappedName="Title"/> </mapping> </mappings> Notice that the namespace was declared on the mappings element and then the prefix was used to specify the element QNames for the name/title properties. This will result in a mapping like so: <np:Employee xmlns:np="urn:north-pole:operations"> <np:Name>Santa Claus</np:Name> <np:Title>Chief Present Officer (CPO)</np:Title> </np:Employee> Ignoring propertiesIf you don't want to serialize a certain property it is easy to ignore it: <mappings> <mapping> <property name="propertyName" ignore="true"/> </mapping> </mappings> Controlling minOccurs and nillableThe default Aegis mapping is to assume that, since any Java object can be null, that the corresponding schema elements should have minOccurs of 0 and nillable of true. There are properties on the mappings for to control this. <mappings>
<mapping>
<property name='everpresentProperty' minOccurs='1' nillable='false'/>
</mapping>
<mappings>
Setting Default minOccurs and nillable Parameters from JavaIf you have many properties, and you want most, or all of them, to have a minOccurs other than 0 or a nillable other than false, you can change the defaults for Aegis from Java code (amongst other places). AnnotationServiceFactory serviceFactory = new AnnotationServiceFactory(); // We 'happen to know' what types are used. AegisBindingProvider binder = (AegisBindingProvider)serviceFactory.getBindingProvider(); DefaultTypeMappingRegistry tmr = (DefaultTypeMappingRegistry)binder.getTypeMappingRegistry(); // here we disuade XFire from its rather annoying tendency to assume that, just because // anything in Java can be null, that we want to advertise all that nullity all over. Configuration configuration = tmr.getConfiguration(); configuration.setDefaultMinOccurs(1); configuration.setDefaultNillable(false); |


Bauhaus University graduate Georg Seifert (b. 1978 in Halle an der Saale, Germany) is a type designer and a software developer. His typeface families Graublau Sans and Graublau Slab have become international bestsellers. He co-developed the typeface for the new Berlin Airport. He is most well known, however, for the font editor ‘Glyphs’, first released in 2011. Seifert lives and works in Berlin.
Laurence Penney is a consultant in font technology based in Bristol, UK. Focussed on dynamic type tech, he specialized in TrueType: coding rasterizers, hinting fonts, and training others how to hint fonts. He later took on the challenge of creating MyFonts, the open platform selling fonts from all foundries, part of the team that made it market leader by a wide margin.
{% if page.short %} {% else %}The recent revival of colour and variable fonts gives Laurence hope that the type world has not forgotten the best ideas from a generation ago and he looks forward to helping these technologies take off. Laurence’s Axis-Praxis website lets anyone play with variable fonts and, by means of Axis-Praxis as well as his talks & workshops, he hopes others will understand what the excitement is all about.
{% endif %}A trained photographer, Rainer Erich (‘Eric’) Scheichelbauer (b. 1977 in Vienna, Austria) holds both a philosophy and a Dutch studies degree. He creates typefaces, works as a digital punchcutter for other type designers, and gives type design workshops on a regular basis.
{% if page.short %} {% else %}Since he has joined the Glyphs team in 2012, he has been writing articles, tutorials, and Python scripts, as well as the blog and the handbook. He lives and works in Vienna, where he runs his type studio Schriftlabor.
{% endif %}One day workshop to learn to build a variable font.
Variable Fonts: the future of type. Learn how to build a variable font in Glyphs, and make it animate, even. You will learn how to set up font projects in Glyphs, add variable font axes to it, and walk home with an emoji animation and a variable font with a few letters and a few axes. You will test it in Axis Praxis, get it to work properly in the latest Adobe apps, and animate it with a little HTML and CSS in a web browser. {% if page.short %}
{% else %}Plus: which Python scripts and plug-ins can help you with building an OTVar font.
No prior experience in type design required. This workshop is for newbies and experienced type designers alike. (If necessary, we split into two groups.)
Be prepared for some fun. :-)


Battleship
The game Battleship is a game in which two players play against each other in an attempt to be the first to sink all of the opponents ships. This is done by correctly guessing the locations of the opponents ships. Only the location of the players own ships is known at the start of the game.In the game, there are four types of ships:
| Label |
Length |
Number of Instances |
| Carrier |
5 |
1 |
| Battleship |
4 |
2 |
| Cruiser |
3 |
1 |
| Submarine |
3 |
2 |
| Destroyer |
2 |
4 |
The game consists of two distinct stages. In the first stage players place their ships on the board in such a way that it is hard for the other player to guess the locations of the ships correctly. This requires the player to have or think of a strategy. The second stage has the players interchangeably guess a potential location of an opponents ship. Once the opponent announces a hit, this may be regarded as a vital hint. A hit means that another potential area to hit exists in at least one of four directions.
If a ship is hit completely, the player has to call which ship is killed. Example: “My Carrier-ship is sunken”
Our adjustments on the game
We did a couple of adjustments to the original game to make it more interesting for a BDI-implementation.
Symmetric guesses:
If one of the players asks the other player a certain location to have a ship placed at it or not, the player himself needs to reveal if at his own board this location contains a ship as well.
By using this type of symmetry in the game, we can make use of common knowledge. Both the players now know that for instance at position x,y there is a ship at player one's board and no ship at player two's board.
New tactics:
Because we now make use of this symmetric guesses, there emerges a new tactic for the BDI-player. It has to say, by the new symmetry, what is placed at his own board at the location that the player is attacking. You don’t want to give away knowledge about your own ship locations, so it is not smart to make an attack at these coordinates. The new tactic could be to guess all kind of coordinates, except for the ones where you have ships as well.


© Bruce Wilcox<EMAIL_ADDRESS>www.brilligunderstanding.com
Revision 6/13/2022 cs13.2
JSON (JavaScript Object Notation) is an open standard format using
human-readable text to transmit data objects over the web. It is a
common standard largely replacing XML which is too wordy and hard to
read. JSON has primitive datatypes (text without doublequotes that
cannot contain any whitespace). These are null, false, true, integers,
and floats. The string datatype is a sequence of characters in double
quotes. JSON also has two datatypes that represent collections of
values, the array and the object. A JSON array is a list of JSON
datatypes separated by commas and placed within square brackets
[]
, e.g.,
[ A, 2, [ help, life], [] ]
Indices of an array start at 0, so the above has as values:
[0] = A
[1] = 2
[2] = an array of 2 values
[3] = an empty array
Note that arrays can hold values of different types. Arrays have no hole in indexing and usually ordered and retain that order, but they work out of order as well (^Jsonmerge can alter the order).
If you have an array, you can use dot notation to find the index of some value in it, eg
$_index = $array.space
will find what array index the value space
is at;
A JSON object is a list of key-value pairs separated by commas and
placed within curly braces {}
, e.g.,
{
"key1": 1,
"bob": "help",
"1": 7,
"array": [1, 2, 3],
"object12": {}
}
Each key is a string (must be encased in double quotes) and joined to
an ending colon. Again types can be mixed in the values. {}
is the empty object, just as []
is the empty array.
Key-value pairs have no guaranteed order and may shuffle around if you
manipulate the structure. You can nest arrays and objects inside each
other.
JSON is an excellent language to represent more complex ChatScript facts as well as interact with the web. ChatScript can convert back and forth between the JSON text string passed over the web and ChatScript facts that represent the structure internally. If you tried to create facts using ^createfact(), you would find making the data shown below extremely difficult and non-obvious. Though it can be done. But as JSON, it is easy to create facts to represent the structure and to access pieces of it.
{
"firstName": "John",
"lastName": "Smith",
"age": 25,
"address": {
"streetAddress": "21 2nd Street",
"city": "New York",
"state": "NY",
"postalCode": "10021-3100"
},
"phoneNumbers": [
{
"type": "home",
"number": "212 555-1234"
},
{
"type": "office",
"number": "646 555-4567"
}
],
"children": [],
"spouse": null
}
JSON facts are triples where the subject is always the name of a JSON
object or array. For objects, the verb of the fact is the name of a
field and the object is its value. Such a structure might be composed of
these facts:
internal CS (jo-3 name Robert) (jo-3 age 10) (jo-3 gender male)
Note that CS does not need to put double quotes around the values or
even the field names (unless the field name has spaces or other unusual
characters within it).
This would correspond to a JSON string that looks like this:
{ "name": "Robert", "age": 10, "gender": "male"}
Actually, the “age 10” fact in ChatScript could represent either what was shown above or:
{ "name": "Robert", "age": "10", "gender": "male"}
For arrays, the verb of the fact is the numeric index in the array and the object is the value. Such a structure might be composed of these facts:
(ja-5 0 Robert)
(ja-5 1 Terry)
(ja-5 2 Paula)
This would correspond to a JSON string that looks like this:
[ "Robert", "Terry", "Paula"]
CS has rich support for creating JSON data. You must create the top level array or object, but after that you can just do assignments somewhat arbitrarily, with CS automatically creating new subobjects or subarrays as needed. E.g. Also note that CS assignments onto object fields do not require you double quote the field name (unless the name as spaces within it or other unusual characters).
$_x = ^jsoncreate(TRANSIENT object)
$_x.field[] = 5
$_x.name.age.birthdate = "January 5, 2020"
In the above, the scripter has explicitly created a transient JSON
object. The 2nd line assignment automatically creates a transient array
to save as the value of field
and then inserts the value 5
into it. The 3rd line assignment automatically creates a field called
name with a JSON object, and that object gets a field called age, and
that object gets a field called birthdate which is assigned the text
string.
Because JSON has distinct data types as values (primitives, text
strings, etc) and CS represents everything as text strings, there are
some issues in moving back and forth in representation. Whereas JSON
shows all strings encased in double quotes, when stored as values in CS
the double quotes are always removed. And JSON primitives
false
, true
, and numbers are also just
strings. Therefore JSON primitive 2
and the JSON string
"2"
are the same to CS. To maintain data type information,
JSON facts have flag bits that describe how to treat the object value of
the fact. This is automatically handled by CS and normally you have no
reason to pay any attention to it.
But when you copy a value out of the fact onto a CS variable, the type data goes away. This is not a problem for CS, except when you want to store the CS variable back into a JSON structure. Then YOU become responsible for knowing the type. CS will assume any of its values that match a JSON primitive will be that, so you need to encase them in double-quotes if you want them to be stored as JSON strings. CS will automatically store everything else as JSON strings and when exporting them to text, will automatically encase them in double quotes. For example,
$_x = ^jsoncreate(TRANSIENT object)
$_x.value = true # JSON boolean primitive
^jwrite($_x) => {"value": true}
$_y = $_x.value
$_x.value = $_y
^jwrite($_x) => {"value": true}
$_x.value = "true" # JSON string true
^jwrite($_x) => {"value": "true"}
$_y = $_x.value
$_x.value = $_y
^jwrite($_x) => {"value": true}
$_x.value = "true" # JSON string true
^jwrite($_x) => {"value": "true"}
$_y = ^join(\" $_x.value \")
$_x.value = $_y
^jwrite($_x) => {"value": "true"}
All this breaks down a bit for the JSON null
primitive
and the empty string ““. CS does not distinguish between having no value
and having a value which has no characters. And CS uses
null
to mean clear a value entirely. So to create a JSON
null value, use the special word json_null
. You can use
that directly in a JSON assignment, or you can put it as the value of a
CS variable which eventually gets used in a JSON assignment.
$_x.value = null # remove the JSON field called value
$_x.value = "null" # assign text string null to field value
$_x = null # remove any value from variable
$_x.value = json_null # special value meaning json null primitive
This just leaves us with the awkwardness of the empty string. You can’t store an empty string onto a CS variable. Instead you store a string with two double quotes. Which CS itself always treats as just that, a two-character string. But when assigned into a JSON structure, any double quoted string has its double quotes stripped. So in JSON we CAN have an empty string. No problem yet. The problem comes in the other direction. Assigning this JSON empty string onto a CS variable clears it (it acts like null). And then putting that variable back onto a JSON structure will save JSON null. So you have to manually track what you want, if you want it.
$_x.value = "" # JSON empty string
$_y = 5
$_y = $_x.value # clears $_y (acts like null)
$_x.value = $_y # assigns JSON null
Note, also, that while JSON is case sensitive in its field names, CS will lookup insensitive. It doesn’t matter if you mis-capitalize the name of a field. CS doesn’t believe you should have two fields with the same name but different capitalization and will treat them as the same.
JSON is case sensitive in field names. CS is not. If you offer a new case field name and it already has a field with a different case, it will use the preexisting one.
Since JSON data structures are implemented as facts, they can use the ^query abilities just as ordinary facts can. Whereas in JSON you can only access data going top down, with CS you can equally access data at any level directly querying on some field name. So depending on how you name a field and whether or not the field only exists for a single object, you might be able to query directly to it.
Note that JSON has no mechanism for sharing JSON subtrees. Hence anytime you create a JSON fact structure in CS, the facts will all be unique. You do this like this:
$_tmp = ^createfact($$jsonobject newfield $$jsondata (FACTTRANSIENT JSON_OBJECT_FACT JSON_OBJECT_VALUE) )
If $$jsonobject is a json object name, you add a field called newfield whose value is a JSON object, thus joining the trees. If you serialize (write into text) these two JSON objects they will become completely separate structures when read back in (JSON doesn’t share).
You will learn how to create JSON structures below. The other key to a web-enabled CS is ^jsonopen(). To see how easy it is to talk to the web, just look at this code.
# The cleanest way to build json data
$_var = ^jsoncreate(transient object)
$_var.fieldname = $myvar
An alternative limited to max output buffer size (~80K):
$_var = ^jsonparse(^"{ fieldname: $myvar }")
And now to send data upstream:
$_url = ^"http://myHost:myIP"
$_userAgent = ^"User-Agent: %bot, ChatScript”
$_header = ^" ~Accept: application/json
$_userAgent
~Content-Type: application/json "
$_response = ^jsonopen(transient POST $_url $_var $_header $_userAgent)
Routines that will create facts for JSON will by default create them
as transients (they die at end of volley unless you work to save them).
You can override this default by saying permanent
or
transient
or boot
. This applies to
^jsonopen
, ^jsonparse
,
^jsoncreate
, ^jsonobjectinsert
,
^jsonarrayinsert
, ^jsoncopy
,
jsonmerge
.
Json arrays all start with the name ‘ja-’ and json objects all start with the name ‘jo-’. The next letter indicates the storage media. ‘t’ means transient and the structure dies at the end of the volley. ‘b’ means boot and the data moves to the boot later at the end of the volley. Anything else (e.g. an immediate digit) means the structure is permanent and is stored in the user’s topic file.
You can also add a flag safe
(described later) to
^jsonparse
, ^jsonobjectinsert
,
^jsonarraydelete
. You can also add a flag
unique
to ^jsonarrayinsert
. You can also add
duplicate
to ^jsonobjectinsert.
When multiple flags are desired, put them into a simple string,
"DUPLICATE PERMANENT"
. Case doesn’t matter.
When you want to add a reference to a normal factid (as is returned
by ^createfact) you can add the flag AUTODELETE
You can also assign user flags by listing USER_FLAG1
,
through USER_FLAG4
as a flag as well. The JSON fact will
have that flag on it, which you can use in conjunction with
^query
to limit what matches can be found.
^jsonstorage
( argument )This expects a json array or object name and returns
permanent
, transient
, boot
or
fails completely depending on what is given it.
^jsonparse
(
{JSONFLAGS} string {~ignoreconcept { ~underscoreconcept} })string
is a JSON text string (as might be returned from
a website) and this parses into facts. It returns the name of the root
node JSON composite. This name will look like this:
ja-0
– a json array numbered 0
.jo-0
– a json object numbered 0
.Note that the above names are true only for PERMANENT JSON objects.
Transient ones will be named like ja-t0
and
jo-t0
.
As new JSON composites are created during a volley, the numbers
increase to keep them all distinct. JSON composites are all created as
transient facts and will die at the end of the volley unless you do
something to explictly keep them (typically ^jsongather
into some factset and then saving that OR using that to remove all their
transient flags OR using ^delete()
to destroy the facts in
the set).
If you are keeping JSON across volleys, you should use the optional Json flags argument to make sure numbering never collides (normally the numbers start back at 0 for each new volley).
Real world JSON has stricter requirements on its format than CS does.
While CS will output strict JSON, you can input slack JSON. You do not need to put commas between elements of an array or object. And you do not need to put quotes around a key name. So the following is legal text form:
[a b {bob: 1 sue: 2}]
Formally JSON has specific primitives named true, false, and null,
that systems may care about, but to CS they are nothing special. Numbers
in JSON can be integer or have a decimal point and an exponent. CS does
not currently support exponent notation, so you can only do:
1325
or 566.23
.
JSON originally required a JSON string be a composite of some kind. Now it allows any JSON type to be a JSON document. CS sticks to the original requirement, because passing around a single value as JSON is pretty useless.
Once you have a JSON fact structure, you can go the opposite direction and convert it back into a string or display it visually.
CS accepts extended JSON syntax for parsing into a json fact structure. Any place you have an object value, you can refer to a ChatScript user or match variable and that value will be substituted in. E.g.,
^jsonparse("{ a: $var, b: _0 }")
Note you should use a regular quoted string and not a function string
like ^"{ a: $var, b: _0 }"
. If you use a function string,
substitution will happen before calling ^jsonparse. Which might be a
problem if you had something like this:
^jsonparse("{ a: $var, b: _0aba }").
where you wanted the value of b
to be
"_0aba"
. Had you used an active string, the _0 would have
been replaced with its contents.
Also, you can use json dereference operators to take apart an existing json structure and use values of it in the current one. If $_y points to a json structure, then
^jsonparse(" opensquiggle a: $var, b: $_y.e[2] closesquiggle ")
(saying squiggles because Latex print complains if I use real ones)
would find a json object reference on $_y
, get the e
field, and get the 3rd array value found there.
An initial argument of safe
will locate the correct end
of the data for json parsing, allowing you to pass excess data. This is
important for passing in json data in OOB information. OOB information
comes in []
and Json itself uses []
at times,
so it would be impossible to find the correct end of pattern with normal
pattern matching. Instead just do:
u: ( \[ _* ) and call ^jsonparse(safe _0)
This will figure out where the OOB marker actually is and only parse within it. You can add NOFAIL before the string argument, to tell it to return null but not fail if a dereference path fails cannot be found.
^jsonparse(transient NOFAIL "{ a: $var, b: _0.e[2] }")
You can pass JSON data on input via OOB notation:
[ {"token": "myid", "accounts": ["whatever"]}] User message
and then have a pattern to grab the OOB data and call
jsonparse
with it (using SAFE as a parameter). OOB input is
not subject to human tokenization behavior, spellchecking, etc.
Note: There is a limit to how much JSON you can pass as OOB data
nominally, because it is considered a single token. You can bypass this
limit by asking the tokenizer to directly process OOB data, returning
the JSON structure name instead of all the content. Just enable
JSON_DIRECT_FROM_OOB
on the $cs_token
value
and if it finds OOB data that is entirely JSON, it will parse it and
return something like jo-t1
or ja-t1
in its
place. Eg. [ { "key": "value} ]
will return tokenized as
[jo-t1]
.
u: GIVEN_JSON(< \[ _* \] ^JsonKind('_0)) $$json = '_0
then you can do $$json.field directly.
Note: ^jsonparse
autoconverts backslash-unnnn into
corresponding the utf8 characters.
Note: You cannot normally send JSON text as normal input from a user because CS tokenization is set to handle human input. So doing something like this as input will not work:
doLogin {"token": "myid", "accounts": ["whatever"]}
But you can pass JSON data directly as part of user input with
warning. But user input normally is limited to 254 tokens AFTER oob is
seen. To be able to pass complex JSON data as part of the user message
(because the oob is often controlled by host system so not available per
user message), you can now put in user input the word json
and follow that with a JSON structure of arbitrary size. That structure
will be completely converted to the corresponding JSON internal fact
structures and the simple JSON structure name returned (regardless of
the setting of tokencontrol). So
my input value is JSON {x:y,b:z} here
will become
my input value is JSON jo-3 here
and jo-3 will have the json structure.
If you have given an ignoreconcept, then whenver a field name is encountered in the incoming data matches the name of a member of that concept set, that field and all data below it are discarded and not returned.
If you have given an underscore concept, then any field name encountered in the incoming data that matches a member of that concept, that field’s string value will have any spaces in it replaced with underscores.’
jsonformat
(string)Because technically JSON requires you put quotes around field names (though various places ignore that requirement) and because CS doesn’t, the function takes in a slack json text string and outputs a strict one.
$myvar.field
and
$myvar[]
If a variable holds a JSON object value, you can directly set and get
from fields of that object using dotted notation. This can be a fixed
static fieldname you give or a user variable value or a match variable
value (quoted or unquoted): $myvar.$myfield
is legal, as is
$myvar._0
or $myvar.'_0
.
Dotted notation is cleaner and faster than ^jsonpath
and
jsonobjectinsert
and for get, has the advantage that it
never fails, it only returns null if it can’t find the field. If the
path does not contain a json object at a level below the top, one will
automatically be created if trying to do assignment, and have the same
transient/permanent property as the immediately containing object. If
the top level variable is not currently an object, assignment will fail.
CS will not create an object for you because it doesn’t know if it
should be transient or permanent.
$x = $$obj.name.value.data.side
$$obj.name.value.data.side = 7
Similarly you can access JSON arrays using array notation:
$x = $$array[5]
$x = $$array[$_tmp]
$$obj.name[4] += 3
$$obj.$_kind[4] += 3
$$obj._0[4] += 3
$$obj.'_0[4] += 3
$x.foo[] = Bruce
If foo is currently undefined, the system will create a JSON array
for you, with permanency that matches the JSON object of $x. You cannot
do $x[] and have this happen because at the top level the system does
not know what permanency to use. Once there is a JSON array in $x.foo,
assignments with foo[]
will add elements to the array. You
can designate the index only if it will be the next index in
succession.
$_x[] = 0 # creates array element 0
$_x[1] = 1 # accepts array element 1 creation request
$_x[3] = 3 # will fail - must be in sequence
You can also do
$_array1 += $_array2 # copies contents of array2 into array1
$_array1 += value # adds value into array1
Adding an element to an array using these notations will automatically select DUPLICATE entries being legal. If you want the insertion to be unique, use ^jsonarrayinsert(UNIQUE xxx xxx) OR in your botmacro change the default by doing
$cs_json_array_defaults = #JSON_ARRAY_UNIQUE
HOWEVER, if you have explicitly created an array using ^jsoncreate, it will add elements based on how you declared it (UNIQUE or DUPLICATE)
The only restriction on arrays is that you cannot add a new array index value without using ^jsonarrayinsert as you are not allowed to create discontiguous indices.
NOTE If a variable has as its value the name of another variable, CS will attempt to autoindirect through it to get to the JSON structure. if x = ′y’ and $y points to a json structure, then $x is indirected and $x.val means $y.val .
NOTE JSON is normally a non-recursive structure with
no shared pointers. But ChatScript allows you to store references to
JSON structures in multiple places of other JSON structures. This has
its hazards. It presents no problem when transcribing to text for a
website using ^jsonwrite
. And when you have something like
this:
$x = ^jsoncreate(object)
$y = ^jsoncreate(object)
$x.field = $y
$x.field1 = $y
$x.field = null
Assuming that a JSON structure is not available in multiple places, the assignment of null (or any other value) to a field that already has a JSON structure will normally cause the old value structure to be fully deleted, since it’s only reference is removed. And the system does check and delete the structure if it is not referred to by some other JSON field. But there are limits. The system has no idea if you have a pointer to it in a variable. Or if it is part of a pathological indirection sequence like this:
$x = ^jsoncreate(object)
$y = ^jsoncreate(object)
$x.field = $y
$y.field = $x
$x.field = null
The two structures point to each other, each only once.
Assigning null
will remove a JSON key entirely. Having a
null value and not having the key are the same from ChatScript’s
perspective (but not from JSON’s)’
For an array, obviously $array[0] returns one end of the array, and you can get the index of The other end by doing
$_tmp = ^length($array) - 1
$array[$_tmp]
But a convenient shortcut is
$array[-1]
For objects, $object[0] returns the name of the most recent field added and $object[-1] returns the name of the first field added.
Just escape the $.
$data.\$varname = hello
^jsonkind
(item)If item is the name of a json array, it returns array
.
If item is the name of a json object, it returns object
.
Otherwise it fails.
^jsonmerge
( {kind}
struct1 struct2)Takes two json arrays or two json objects and adds unique elements of struct2 into struct1 recursively.
If kind
is key
and the two structs are
arrays of objects, then unique objects from the second array are added
to the first array (this is the default). Unique meaning that the first
property from the object does not exist. If kind
is
key-value
is like key
but the uniqueness test
is extended to the property value as well. If kind
is
sum
and the two structs are objects, then the values for
the same property name in the two objects are added together. If
kind
is sumif
is like sum
but
items in struct1
are only kept if they are also in
struct2
.
^jsoncount
(struct
depth)Walks the given JSON structure, displaying it, except that for arrays arising after depth, just the count of elements is shown
^jsonpath
( string id )string
is a description of how to walk JSON.id
is the name of the node you want to start at
(typically returned from ^jsonopen
or
^jsonparse
).Array values are accessed using typical array notation like
[3]
and object fields using dotted notation. A simple path
access might look like this: [1].id
which means take the
root object passed as id, e.g., ja-1
, get the 2nd index
value (arrays are 0-based in JSON).
That value is expected to be an object, so return the value
corresponding to the id field of that object. In more complex
situations, the value of id might itself be an object or an array, which
you could continue indexing like [1].id.firstname
.
You can walk an array by using [$_index]
and varying the
value of $_index
.
When you access an array element, you have to quote the text because
it consists of multiple tokens to CS which breaks off [
and
]
. If you are just accesing an object field of something,
you can quote the string or just type it directly
^jsonpath(.id $object2)
^jsonpath(".id" $object2)
Of course you don’t always have to start at the root. If you know
what you want is going to become object 7 eventually, you could directly
say .id given jo-7
and the system would locate that and get
the id field. Likewise if you know that key names are somehow unique,
you could query for them directly using
^query(direct_v ? verbkey ?)
Or even if the key is not unique you can restrict matches to facts
having the JSON_OBJECT_FACT
flag.
^query(directflag_v ? verbkey ? 1 ? ? ? JSON_OBJECT_FACT)
Be aware that when ^jsonpath
returns the value of an
object key, when the value is a simple word, it just returns the word
without doublequotes (since CS just stores information as a single
word). But if the value contains whitespace, or JSON special characters,
that may mess up if you pass it to ^JSONFormat
. You can get
^jsonpath
to return dangerous data as a string with double
quotes around it if you add a 3rd argument “safe” to the call.
^jsonpath(".name" $_jsonobject safe)
^jsonpath
Generally speaking the direct access methods are clearer than using this function.
Can also return the actual factid of the match, instead of the object of the fact. This would allow you to see the index of a found array element, or the json object/array name involved. Or you could use ^revisefact to change the specific value of that fact (not creating a new fact). Just add * after your final path, eg
^jsonpath(.name* $$obj)
^jsonpath(.name[4]* $$obj)
Correspondingly, if you are trying to dump all keys and values of a JSON object, you could do a query like this:
@0 = ^query(direct_s $_jsonobject ? ?)
^loop()
{
_0 = ^first(@0all)
and then you have _1 and _2 as key and value
}
If you need to handle the full range of legal keys in json, you can
use text string notation like this
^jsonpath(."st. helen".data $tmp)
.
You may omit the leading . of a path and CS will by default assume it
^jsonpath("st. helen".data $tmp)
This is like ^loop, but explicitly for json data. It is faster and cleaner than writing a loop. A normal loop might look like:
$_count = ^length($_jsonarray)
^loop($_count)
{
$_count -= 1
$_value = $_jsonarray[$_count]
...
}
And similarly for a JSON object one might want:
$_count = ^length($_jsonobject)
^loop($_count)
{
$_count -= 1
$_jsonfield = $_jsonobject[$_count]
$_value = $_jsonobject.$_jsonfield
...
}
But for large numbers of elements (eg a thousand +) this is ineffient because it has to search for each element each time. The efficient way is:
^jsonloop($_jsonobject $_field $_value)
{
...
}
where the loop runs most recent entry to least recent, putting the
field name in $_field
and its value in
$_value
. Similarly for a jsonarray it does the index as
$_field
and $_value
is its value.
You can choose (or annotate) which way the loop runs by adding an optional 3rd argument OLD or NEW.
^jsonloop($_jsonarray $_index $_value OLD) will walk oldest first (i.e. index 0 and increasing).
^jsonloop($_jsonarray $_index $_value NEW) will walk newest first (i.e. index max and decreasing).
^length
( jsonid )Returns the number of top-level members in a json array or object.
^jsonwrite
( {plain} name
)name is the name from a json fact set (either by
^jsonpart
, ^jsonopen
, or some query into such
structures). The result is the corresponding JSON string (as a website
might emit), without any linefeeds. plain
is an optional
first argument that makes it write out less noisy JSON that CS already
accepts, ie field names and string values dont need double quotes around
them unless they have certain characters in them (like spaces and
semi-colons and escape characters). This makes data output from CS and
intended to be read back into CS easier to read. So
jo-5 which is {"value":"color"} prints as {value:color}
^jsontree
( name {depth}
{array})name is the value returned by ^jsonparse
or
^jsonopen
or some query into such structures. It displays a
tree of elements, one per line, where depth is represented as more
deeply indented. Objects are marked with {}
as they are in
JSON. Arrays are marked with []
.
The internal name of the composite is shown immediately next to its opening punctuation. Optional depth number restricts how deep it displays. 0 (default) means all. 1 means just top level.
Optional “array” means show number of array elements rather than the elements themselves at any depth below depth.
You can build up a JSON structure without using
^jsonparse
if you want to build it piece by piece. And you
can edit existing structures.
^jsoncreate
( {JSONFLAGS}
type )Type is either array
or object
and a json
composite with no content is created and its name returned. See
^jsonarrayinsert
, ^jsonobjectinsert
, and
^jsondelete
for how to manipulate it. See writeup earlier
about optional json flags.
The system makes ids with different names for build0, build1, and user. And increments ids as it creates new ones. If the id created already exists, the system increments and tries again. If there are lots of collisions you can speed things up by setting $cs_jid. This changes the number to start with.
^jsonarrayinsert
(
{JSONFLAGS} arrayname value )Given the name of a json array and a value, it adds the value to the end of the array. See writeup earlier about optional json flags. If you use the flag unique then if value already exists in the array, no duplicate will be added.
^jsonarraydelete
(
[INDEX
, VALUE
] arrayname value )This deletes a single entry from a JSON array. It does not damage the thing deleted, just its member in the array.
INDEX
, then value is a number
which is the array index (0 … n-1).VALUE
, then value is the value
to find and remove as the object of the json fact.You can delete every matching VALUE
entry by adding the
optional argument ALL
. Like:
^jsonarraydelete("VALUE ALL" $array 4)
If there are numbered elements after this one, then those elements immediately renumber downwards so that the array indexing range is contiguous.
If the key has an existing value then if the value is a json object
it will be recursively deleted provided its data is not referenced by
some other fact (not by any variables). You can suppress this with the
SAFE
flag.
^jsonarraydelete(SAFE $obj $key)
.
^jsonreusekill
(
$jsonstruct )Kills the facts of this struct and makes them immediately available for reuse as free facts.
^jsonarraysize
( name )deprecated in favor of ^length
^jsontext
(factid)^jsontext adds quotes if object of fact is a json text and FAILS if object is not a json fact.
CS represents json text as ordinary unquoted text, but text that looks like float numbers would be subject to possible float truncations or expansion of digits. This preserves it as text.
^jsoncopy
( name )Given the name of a json structure, makes a duplicate of it. If it is not the name of a json structure, it merely returns what you pass it.
^jsonmerge
(
{creation_arg} control arg1 arg2 )^jsonmerge take two json structures and perform a top level merge. The result is a copy of the first argument, with top level fields augmented with fields from arg2 not found in arg1. Optional first argument is the standard one for many Json creation functions.
Control describes how to merge fields of json objects.
key
means if arg1 already has this key, ignore the
corresponding field from arg2. key-value
means add in the
field and value unless they are the same.
You can also request the system to sum values of fields of objects
with control values of sum
or sumif
.
^jsonobjectinsert
(
{JSONFLAGS} objectname key value )inserts the key value pair into the object named. The key does not
require quoting. Inserting a json string as value requires a quoted
string. Duplicate keys are ignored unless the optional 1st argument
DUPLICATE
is given. See writeup earlier about optional json
flags.
If the key has an existing value and DUPLICATE
is not a
factor, then if the value is a json object it will be recursively
deleted provided its data is not referenced by some other fact (not by
any variables). You can suppress this with the SAFE
flag.
jsonobjectinsert(SAFE $obj $key null)
.
^jsondelete
( factid )deprecated in favor of ^delete
^jsongather
(
{fact-set} jsonid {level})takes the facts involved in the json data (as returned by
^jsonparse
or ^jsonopen
) and stores them in
the named factset.
This allows you to remove their transient flags or save them in the
users permanent data file.
You can omit fact-set as an argument if you are using an assignment
statement: @1 = ^jsongather(jsonid)
^Jsongather
normally gathers all levels of the data
recursively. You can limit how far down it goes by supplying
level
. Level 0 is all. Level 1 is the top level of data.
Etc.
^jsonlabel
( label )assigns a text sequence to add to jo- and ja- items created thereafter. See System functions manual.
^readfile
(
TAB filepath {‘^fn}) and ^readfile
( LINE filepath’^fn)reads a tsv (tab delimited spreadsheet file) and returns a JSON array representing it. The lines are all objects in an array. The line is an object where non-empty fields are given as field indexes. The first field is 0. Empty fields are skipped over and their number omitted.
If an optional 3rd parameter of a function name is given, the code
does not create a JSON structure to return. Instead it calls the
function with each field of a line being an argument. This is sort of
analogous to :document
mode in that you can potentially
read large amounts of data in a single volley and may need to use
^memorymark
and ^memoryfree
to manage the
issue.
^readfile ( LINE filepath 'function)
reads a file and
passes each line untouched as the sole argument to the function.
Formerly called ^jsonreadfile (still accepted).
An input line can be :trace all or :trace none to observe behavior of the data between them.
^jsonundecodestring
(
string )removes all json escape markers back to normal for possible printout to a user. This translates \n to newline, \r to carriage return, \t to tab, and \” to a simple quote.
^jsonopen
(
{JSONFLAGS} kind url postdata header {ignoreconcept {underscoreconcept}
} {timeout})this function queries a website and returns a JSON datastructure as facts. It uses the standard CURL library, so it’s arguments and how to use them are generally defined by CURL documentation and the website you intend to access. See writeup earlier about optional json flags.
| parameter | description |
|---|---|
kind |
is POST , GET , POSTU ,
GETU , PUT , DELETE corresponding
to the usual meanings of Get and Post and url-encoded forms. |
url |
is the url to query |
postdata |
is either “” if this is not a post or is the data to send as post or put |
header |
is any needed extra request headers or ““. Multiple header entries must be separated by a tilde |
timeout |
optional seconds limitation for connection and then for transfer. else $cs_jsontimeout rules |
Note: ‘postdata’ can be a simple JSON structure name, in which case the system will automatically perform a ^jsonwrite on it and send that text data as the data. Currently limited to 500K in size of the internal buffer.
A sample call might be:
$$url = "https://api.github.com/users/test/repos"
$$user_agent = ^"User-Agent: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)"
^jsonopen(GET $$url "" $$user_agent)
where GitHub requires user-agent data.
As an example of a complex header value you might create neatly,
$header = ^"Accept: application/json
~Accept-Encoding: identity,*;q=0
~Accept-Language: en-US,en;q=0.5
~Cache-Control: no-cache
~Connection: close
~Host: Chatscript
~User_Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:42.0) "
ChatScript will make each line have a single space separator between line continuations. And JsonOpen will correctly get the header elements that do not include that spacing.
The results are a collection of facts representing the JSON parse
tree and the value of the function is the root JSON value. The JSON
elements that can be represented are arrays, objects, JSON strings, and
primitives (numbers, true, false, null). JSON arrays are named
ja-n
where n
is a unique index. JSON objects
are similarly named jo-n
.
Unlike JSON, which makes a distinction between primitives and strings, in ChatScript those things are all strings and are not quoted. So a JSON string like this:
[ {"id": 1 "value": "hello"} {"id": 2 "value": "bye"} ]
returns this value: ja-1
and these facts. The facts have
flags on them which you can use in queries. You may not have any need to
use these flags, so maybe you will just ignore their existence.
| fact | associated flags |
|---|---|
| (ja-1 0 jo-1) | #JSON_ARRAY_FACT
#JSON_OBJECT_VALUE |
| (jo-1 id 1) | #JSON_OBJECT_FACT
#JSON_PRIMITIVE_VALUE |
| (jo-1 value hello) | #JSON_OBJECT_FACT
#JSON_STRING_VALUE |
| (ja-1 1 jo-2) | #JSON_ARRAY_FACT
#JSON_OBJECT_VALUE |
| (jo-2 id 2) | #JSON_OBJECT_FACT
#JSON_PRIMITIVE_VALUE |
| (jo-2 value bye) | #JSON_OBJECT_FACT
#JSON_STRING_VALUE |
Using queries, you could get all values of an array. Or all fields of
an object. Or all JSON facts where the field is the id. You could
manually write script to walk the entire tree. But more likely you will
use ^jsonpath
to retrieve specific pieces of data you want.
For example, you could do a query on the value returned by
^jsonopen
as subject, to find out how many array elements
there are. Then use ^jsonpath
to walk each array element to
retrieve a specific field buried within.

You can also ask CS to show those out visually using
^jsontree
.
Note that the facts created are all transient and disappear at the
end of the volley unless you have forced them to stay via
permanent
. Forcing them to stay is generally a bad idea
because it will congest your user topic data file, slowing it down or
exceeding its capacity, and because those facts may then collide with
new facts created by a new ^jsonopen
on a new volley. The
array and object ids are cleared at each volley, so you will be reusing
the same names on new unrelated facts.
Using the flag values, it is entirely possible to reconstruct the original JSON from the facts (if the root is an array or object because otherwise there are no facts involved), but I can’t think of use cases at present where you might want to. You cannot compile CS on LINUX unless you have installed the CURL library. For Amazon machines that means doing this:
sudo yum -y install libcurl libcurl-devel
Or more completely, for evserver and curl, you might do:
sudo yum -y install -y libc -devel gcc libc6 -compat libcurl libcurl-devel libstdc++ libgcc glibc make gcc-c++
On some other machines that doesn’t install library stuff and maybe you need
sudo apt-get install libcurl3 libcurl3-gnutls libcurl4-openssl-dev
System variables %httpresponse
will hold the most recent
http return code from calling ^jsonopen
.
If you call ^jsonopen(direct ...)
then the result will
not be facts, but the text will be directly shipped back as the answer.
Be wary of doing this if the result will be large (>30K?) since you
will overflow your buffer without being checked.
^jsonopen automatically url-encodes headers and urls
Note: CS blocks until the call is complete. On a production server if you expect that the call can take serious time, you are advised to send the request in OOB to your own additional layer which returns to CS immediately. Then it makes the call and when the call completes, makes a call back to CS with the results in OOB.
You can set dynamic time limits on ^jsonopen. The variable $cs_jsontimeout sets a local seconds limit on the call. -1 means fail immediately.
If you have a variable $correlation_id, this value will be passed to jsonopen as an additional header correlation-id: %s. Used to track across multiple calls in a system what the originating message was.
If you have given an ignoreconcept, then whenver a field name is encountered in the incoming data matches the name of a member of that concept set, that field and all data below it are discarded and not returned.
If you have given an underscore concept, then any field name encountered in the incoming data that matches a member of that concept, that field’s string value will have any spaces in it replaced with underscores.’ I
JSONOpen and local files
JSONOpen is a wrapper around the Curl
library, so you
can use as an url a local file reference like
file:///c:/myfile.txt
. The file, of course, should be a
JSON text string.
JSONOpen and proxy servers
If you need JSONOpen to run thru a proxy server, these are the CS
variables you need to set up: $cs_proxycredentials
should
be your login data, e.g. myname:thesecret
.
$cs_proxyserver
is the server address, e.g.,
http://local.example.com:1080
. $cs_proxymethod
are bits listing the authorization method to use. They come from the
LIBCURL so you should OR together the bits you want. Bit 1 is the most
basic choice of name and password. Read-
https://curl.haxx.se/libcurl/c/CURLOPT_HTTPAUTH.html
Out-of-band data in ChatScript is signaled by the output beginning
with data enclosed in []
. Which might be confusing, since
JSON uses []
to denote an array. Standalone ChatScript
contains a built-in handler for OOB data and if you pass it JSON at the
start of output, it will swallow it and not display it (unless you turn
on OOB display).
Similarly, std webpage interfaces connecting to ChatScript do likewise. So if you want to see this information, you should put something in the output at the start which is NOT the JSON data. Anything will do. The only time you might actually need the JSON clean at the beginning is from some special purpose application, and in that case you will write your own OOB handler anyway (or not have one).
OOB data into ChatScript is similarly signaled by being at the start of input, with data enclosed in [], followed typically by the user’s actual input. The ChatScript engine reacts specially to OOB incoming data in that it will be careful to not treat it like ordinary user chat. Tokenization is done uniquely, spell-checking, pos-tagging, parsing, named entity merging etc are all turned off and the data becomes its own sentence (the user’s actual input generates more sentences to CS as input). OOB data is then processed by your script in any way you want. So one clever thing you can do is pass in JSON data within the OOB to get temporary facts into your app during a volley. Input might look like this:
[ [ a b { "bob": 1, "suzy": 2 } ] ] What is your name?
You can pattern match the oob section of the input as follows:
u: ( \[ _* ) $_tmp = ^jsonparse('_0)
_0
will contain an excess right bracket (the end of the
oob message), but that won’t bother ^jsonparse
.
Representing JSON in CS facts is more than just a bunch of subject-verb-object facts linked together.
The facts have typing bits on them that describe the structure and
arrays have index values that must remain consistent. Therefore you
should not create and alter JSON fact structures using ordinary CS fact
routines like ^createfact
and ^delete
. Instead
use the JSON routines provided.
The write routines jsonwrite
and jsontree
print out different views of the same data..
u: (-testcase1) $_jsonObject = ^jsoncreate(object)
ˆjsonobjectinsert( $_jsonObject name “some name” )
ˆjsonobjectinsert( $_jsonObject phone “some number” )
ˆjsonwrite ( $_jsonObject ) \n
^jsontree ( $_jsonObject )\n
Note in this next example how to escape a json string with ^’’. This makes creating json objects from static data very intuitive and clear.
u: (-testcase2) $_tmp = ^jsonparse( ^'{name: "Todd Kuebler", phone: "555.1212"}' )
^jsonwrite( $_tmp ) \n
^jsontree( $_tmp ) \n
name: $_tmp.name, phone: $_tmp.phone
This example shows the . notation access of data inside a json object in chatscript. This is probably the most intuitive way of interacting with the data.
u: (-testcase3) $_tmp = ^jsoncreate(object)
$_tmp.name = "Todd Kuebler"
$_tmp.phone = "555-1212"
^jsonwrite( $_tmp ) \n
^jsontree( $_tmp ) \n
name: $_tmp.name, phone: $_tmp.phone
In the example below, we add two items into an array of objects and we display the formatted array:
u: ( testcase4 )
# create a phoneBook as an array of structured items (objects)
$_phoneBook = ^jsoncreate(array)
# add first object in the array
#
$_item = ^jsoncreate(object)
# assign values
$_item.name = "Todd Kuebler"
$_item.phone = "555-1212"
^jsonarrayinsert($_phoneBook $_item)
# add a second object in the array
#
$_item = ^jsoncreate(object)
# assign values
$_item.name = "Giorgio Robino"
$_item.phone = "111-123456789"
^jsonarrayinsert($_phoneBook $_item)
# display JSON tree
^jsontree( $_phoneBook ) \n
#
# print formatted items in the phone book
#
phone book:\n
$_i = 0
$_size = ^length($_phoneBook)
loop($_size)
{
# print out formatted item
name: $_phoneBook[$_i].name, phone: $_phoneBook[$_i].phone\n
$_i += 1
}


translate any language into major languages of the world. there is certain limit to the number of translation present per-month uptill which its free( for non commercial use and development purpose )
documentation of google translateThis is fast and customisable QR Code generator. It gives possibility for obtain QR code image dynamically in your solution through API interface. Detailed description of usage in available in the Docs section. As this API is at the early stage of development, feel free to ask questions or share your ideas for further directions of its growth.
documentation of google translateCreate unique looking QR codes with logo, color and design as PNG, SVG, PDF or EPS. QR Codes can be generated in high quality for print and professional use cases.
documentation of QR Code with logo


Circle inversion expands the size of output pixels. Close to the border they become much larger than input image pixels.
Sampling the color of only one input image pixel gives bad results due to aliasing (similar to texture mapping in video games.)
Solution:
I am using instead an average of input image pixels.
Area of averaging lies around mapped output image pixel using its mapped size.
This is fast using summed area tables and easy to program in plain vanilla javascript.
Alternative: Mipmaps, using openGL and the processors of the graphics card.
More acurate, but too expensive: Averaging using a subdivision of the output pixel (subsampling). Depends on the size of the mapped pixel.
| center   | |
| left | |
| right |
Also improves image quality far away from the border!
Additional improvement: Smoothing the jaggies at the border of the disc!