Android SDK Setup
Please refer to our GitHub documentation for detailed information. The following page gives an overview of how to get started with the Android Wallet SDK.
1. Interfaces and workflows
Android Wallet SDK consists of an interface
and workflows
.
Interface
Callback functions are used for communication between app and Wallet SDK In Android Wallet SDK these callback functions are provided as an interface
2. Requirements
| Item | Supported Version |
|---|---|
Android API |
22 and above |
Java Compile |
1.7 |
:::warning Android Apps that support Android API versions 21 and below OST Wallet SDK cannot work in Android Apps with version 21 and below, the minimum Android API version it can work with is 22 (Android Lolipop).
If your Android App supports minimum Android API version lower than Lolilop (Android API 22), the Wallet SDK will break for users running Android API versions lower than Lolipop (Android API 22). :::
- :::note Android API versions 21 and below To use the SDK with an application that supports Android API below 22, please follow the steps below
-
-
By default, when importing a library with a
minSdkVersion
value that’s higher than the main manifest file, an error occurs and the library cannot be imported. To make the merger tool ignore this conflict and import the library while keeping your App’s lowerminSdkVersion
value, add theoverrideLibrary
attribute to the<uses-sdk>
tag.
-
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.app"
xmlns:tools="http://schemas.android.com/tools">
...
...
...
<uses-sdk tools:overrideLibrary="com.ost.walletsdk"/>
-
Use conditional initialization for Andriod API version 22 and above.
public static final String OST_PLATFORM_API_BASE_URL = "https://api.ost.com/testnet/v2";
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
OstSdk.initialize(getApplicationContext(), OST_PLATFORM_API_BASE_URL);
}
3. Install Android Wallet SDK
i) Update build.gradle files
Create config file named ost-mobilesdk.json
file in app/src/main/assets/
path of your android project.
Paste following contents in app/src/main/assets/ost-mobilesdk.json
file
{
"BLOCK_GENERATION_TIME": 3,
"PIN_MAX_RETRY_COUNT": 3,
"REQUEST_TIMEOUT_DURATION": 60,
"SESSION_BUFFER_TIME": 3600,
"PRICE_POINT_TOKEN_SYMBOL": "OST",
"PRICE_POINT_CURRENCY_SYMBOL": "USD",
"USE_SEED_PASSWORD": false
}
| Attribute | Description |
|---|---|
BLOCK_GENERATION_TIME |
The time in seconds it takes to mine a block on auxiliary chain. |
PIN_MAX_RETRY_COUNT |
Maximum retry count to get the wallet Pin from user. |
REQUEST_TIMEOUT_DURATION |
Request timeout in seconds for https calls made by ostWalletSdk. |
SESSION_BUFFER_TIME |
Buffer expiration time for session keys in seconds. |
PRICE_POINT_TOKEN_SYMBOL |
This is the symbol of base currency. So its value will be OST. |
PRICE_POINT_CURRENCY_SYMBOL |
It is the symbol of quote currency used in price conversion. |
USE_SEED_PASSWORD |
Uses mnemonics and password to generate seed. |
:::warning These configurations are MANDATORY for successful operation. Failing to set them will significantly impact usage. :::
4. Initialize the Wallet SDK
SDK initialization should happen before calling any other workflow
.
To initialize the SDK, we need to call initialize
method of Wallet SDK.
Recommended location to call init() is in Application sub-class.
import android.app.Application; import com.ost.mobilesdk.OstWalletSdk; public class App extends Application { public static final String OST_PLATFORM_API_BASE_URL = "https://api.ost.com/testnet/v2"; @Override public void onCreate() { super.onCreate(); OstWalletSdk.initialize(getApplicationContext(), OST_PLATFORM_API_BASE_URL); } }
5. Setting up communication between app and Wallet SDK
Wallet SDK provides workflows
that can be called by any Android activity class or fragment class to perform wallet related actions.
Communication between app and Wallet SDK happens through callback functions.
We need to pass these callback functions in workflows
provided by SDK.
The group of callback functions for communication between app and Wallet SDK is provided in OstWorkFlowCallback
interface.
a). Implementing the OstWorkFlowCallback
interface
There are different ways to pass these callback functions in workflows.
We will create a BaseFragment
for reusability purpose which will implement OstWorkFlowCallback
interface.
The Wallet SDK does not hold strong reference of workflow callbacks. It only has a weak reference of workflow callback. This is done to avoid any memory leaks. The app should hold the reference of the callbacks as long as it needs.
public class BaseFragment extends Fragment, OstWorkFlowCallback {
@Override
public void flowComplete(
OstWorkflowContext ostWorkflowContext, OstContextEntity ostContextEntity) {
String workflowType = ostWorkflowContext.getWorkflow_type();
String entity = ostContextEntity.getEntityType()
String completeString = String.format("Workflow %s complete entity %s ", workflowType, entity);
Toast.makeText(OstWalletSdk.getContext(), "Work Flow Successful", Toast.LENGTH_SHORT).show();
}
@Override
public void flowInterrupt(
OstWorkflowContext ostWorkflowContext,
OstError ostError) {
String workflowType = ostWorkflowContext.getWorkflow_type();
String errorMessage = ostError.getMessage();
String errorString = String.format("Work Flow %s Error: %s", workflowType, errorMessage);
Toast.makeText(OstWalletSdk.getContext(), errorString, Toast.LENGTH_SHORT).show();
}
// More callback functions definitions here
....
....
}
OST Wallet App
To provide developers with sample integration of Wallet SDK, OST Wallet Android app is available on GitHub.
Next Steps
-
Android Wallet SDK Methods, Interfaces and Classes


DI-DAK-SOL
- sodium hypochlorite solution
Century Pharmaceuticals, Inc.
Disclaimer: This drug has not been found by FDA to be safe and effective, and this labeling has not been approved by FDA. For further information about unapproved drugs, click here.
Uses
To prevent and treat infection of the skin and tissue.Directions
Pour on or apply to affected area. For wound management, use as an irrigant,
cleanser, or the wetting agent for a wet-to-moist dressing. Apply once daily for
lightly to moderately exudative wounds. Apply twice daily for highly exudative
or highly contaminated wounds. Protect surrounding intact skin with a moisture
barrier ointment or skin sealant as needed.
Other Information
Store at room temperature.
May bleach clothing.
Keep container closed when not using.
|
DI-DAK-SOL
sodium hypochlorite solution | |||||||||||||||
| |||||||||||||||
| |||||||||||||||
| |||||||||||||||
| |||||||||||||||
|
| Labeler - Century Pharmaceuticals, Inc. (042815464) |
| Establishment | |||
| Name | Address | ID/FEI | Business Operations |
|---|---|---|---|
| Century Pharmaceuticals, Inc. | 042815464 | pack, analysis, manufacture, label |


--- layout: post esbma_id: 1640 title: Localization just doesn't matter date: 2006-11-20 19:56:26 ---
Two weeks ago, SourceGear was an exhibitor at the trade show portion of Tech-Ed in Barcelona, Spain. This was the first time we have been to this event. In fact, it was the first time SourceGear has been to any trade show outside the United States.
Personally, I have always wanted to attend Tech-Ed in Barcelona. The event seems to move back and forth between Barcelona and Amsterdam. The latter doesn't interest me at all, but I love Spain. Going to Barcelona for business would be great, and appending a family vacation would be even better.
But although we have considered this trip in the past, I have always resisted it. Even this year, it was all Corey's idea. He thought we should go, and it obviously didn't take too much arm-twisting for me to agree, so we went.
But my basic hesitancy remained a concern. I have never advocated attending a trade show in Europe, for one reason: Our software is English-only.
To me, it just seems odd to show up at a European trade show with software that is not internationalized. As I said in my post from Barcelona two weeks ago, I expected to spend the entire week apologizing for the fact that we have not localized our products for French, German, Italian, Spanish, Portuguese, Greek, Russian, Hebrew, Polish, or Catalan.
I have always believed that i18n and l10n are important. Or, to put it another way, I have always felt guilty for the fact that SourceGear doesn't really do much in this area. :-)
Seriously, localization is one of those features that we never seem to have time for. It's on the list for every release, and it gets cut from every release. I feel kind of embarrassed about it. I'm proud to be an American, but, well, sometimes I'm not. I never wanted to SourceGear to be one of those arrogant American software companies that simply expects everybody to speak English.
But right now, that's what we are. So I just figured we would spend the week in Barcelona receiving complaints from people who want Vault in their own language. And we planned to be gracious as we received those gripes, because we deserve them.
But that's not what happened.
We had two booths at this show, one for each division of our company, SourceGear and Teamprise. There were 7,500 attendees from all over Europe and beyond. The booths were open for four days. We spoke with hundreds of customers and prospects. We received lots of valuable feedback. People asked us for all kinds of features.
Nobody asked us to localize our products for another language.
I'll repeat that, just in case you missed it. Here is the total number of people who asked us about localizing our products in languages other than English: Zero. Cero. Nul. Zéro. Null. Нул. Μηδέν.
I found this to be simply shocking.
Yes, yes, I know that there were some factors biasing things toward this result:
I know all that, so don't post it in my comments.  :-)
Still... Zero.
Boggles the mind, doesn't it?
This data point is a biggie. Here are a few more:
I now find myself in a very strange place. Empirical data simply doesn't match my expectations. The world should be punishing me for my arrogant "American-English-is-the-only-language-that-matters" behavior, but it's not. Our foreign revenues are solid. We've experimented with localization and received abysmal results. We've been to a trade show where most people's first language is not English, and nobody even complained.
I am forced to conclude that localization just doesn't matter. This isn't the conclusion I expected. It's not the conclusion I wanted. It doesn't fit my intuition. But it's the only conclusion that fits the data I've got.
Tell me I'm wrong. I'll listen. But right now, Vault is English-only, and I think maybe I'm ready to stop feeling guilty about it.


Stereo (1969) & Crimes of the Future (1970) 65m each.
David Cronenberg once had ambitions to be an "obscure science fiction novelist" prior to his film-making career, and it shows through in these two trial works, which are so similar to each other and yet so distinct from his other films that they cannot help but be discussed together. They are not recommended as general viewing but should be of interest to Cronenberg completists in that they establish the themes of sexuality, mutation and medicine prevalent in most of his subsequent work.
Cronenberg's debut STEREO is the result of his interest in underground film - it may aspire to be experimental but comes across more like a student project. There is no live sound, but a voice-over spoken by different narrators who sound as if they are taking turns reading from the same medical journal. The storyline - if it can be called that - describes an experiment by a research facility in Ontario to accelerate telepathic abilities among a group of young subjects. As a kind of punchline, the film ends inconclusively, with the narration stating that all the events we have seen in the film are in need of yet further analysis.
It's hard to say whether STEREO succeeds or fails without knowing Cronenberg's real intent - as a stand-alone experimental film it's no better or worse than many other student features, but if its aim is to portray a fictitious medical report in a documentary style, then it does so suitably. All of this is to the expense of involvement, however. The bloodless delivery of unending pseudoscience makes this difficult viewing, although there are some intriguing nuggets buried within (Cronenberg's wry take on heterosexuality, for example). In fact, STEREO rejects the notion of film as a medium of communication and sets out, almost as a put-on, to alienate its viewers instead: Cronenberg is more interested in framing his 'actors' within chic, modernist buildings than providing his visuals with any human impetus; the lengthy silent passages give us a rest from the unwieldy narration but do not serve to clarify what anyone in the film is feeling; and the only real 'action' sequence, in which someone is chased through a building, is no more than a psychic projection. I don't think this is misjudgment on Cronenberg's part. By crafting his film in a subconscious, elusive manner, he may have hoped to simulate the subject of his story - because we see no characters speak and understand only fragments of what we hear in between the silences, it may be that STEREO tries to be a conduit to its own telepathic essaying.
STEREO has much in common with its nominal companion piece, CRIMES OF THE FUTURE. They have identical running times, the same cast, and share the same filming approach (silent with voice-overs added) and visual sense (people continuously framed against architecture). The narration of the latter is a little less technical, but just as oblique and delivered even more soporifically. It is these similarities that make it hard to separate the two beyond the most technically apparent features - that is, CRIMES is in color and its soundtrack is punctuated by intrusively dubbed biological sound effects. But whereas STEREO examines the evolution of mental processes that would eventually culminate in films like SCANNERS and THE DEAD ZONE, CRIMES ponders on the evolution/regression/mutation of the body itself - ideas which Cronenberg would develop more fully in RABID, VIDEODROME, and THE FLY (THE BROOD would be his ultimate collision of both themes). The storyline of CRIMES is more expansive and science-fictional: a young doctor explores different medical disciplines/factions that have evolved from research into an apocalyptic disease. These vary in scope from dermatology to neo-venereal diseases to a sort of therapeutic podiatry - by the time it gets to this level you get the impression that Cronenberg is pulling the audience's leg as well his cast's.
Delivered once again in the stoic, emotionless manner of STEREO, CRIMES, like its predecessor, also serves to alienate, although this time it uses the device as a reflection of its characters. Theirs is an austere, clinical world in which the child-bearing female population has all but died out. The only purpose of the male survivors is to formulate, research, and experiment. By the film's end their conclusions should be provocative but instead become just as detached as everything else that has gone before, leaving us to wonder what the 'crimes' of the future really are. Or perhaps, ending where the film does, the title refers to crimes of the future beyond that of the present story. It could be for this reason that in the final scene the protagonist sheds a single tear. It's about time: after two features and two hours of calculation, Cronenberg is ready to put his obsessions to more direct work. What's probably most interesting about this intimate pair of films is that they give no indication of the global cult status and success that their director was to earn. Footnote: Cronenberg gave 1998's eXistenZ the working title CRIMES OF THE FUTURE, which led to many fans anticipating - or dreading - a revisitation of his early experimental style.
<EMAIL_ADDRESS>Get Your Private, Free E-mail from MSN Hotmail at http://www.hotmail.com
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


#include <expat.h>
Go to the source code of this file.
Data Structures | |
| struct | AttrList |
| Information for an attribute. More... | |
| struct | AttrBlock |
| Information for a block of attributes. More... | |
| struct | elem_t |
| struct | node |
| struct | Stack |
| This is a structure that holds the information for a stack. More... | |
Defines | |
| #define | VOT_DOC_VERSION "1.2" |
| #define | VOT_XSI "http://www.w3.org/2001/XMLSchema-instance" |
| #define | VOT_SCHEMA_LOC "http://www.ivoa.net/xml/VOTable/v1.1 http://www.ivoa.net/xml/VOTable/v1.1" |
| #define | VOT_XMLNS "http://www.ivoa.net/xml/VOTable/v1.1" |
| #define | SZ_ATTRNAME 32 |
| #define | SZ_ATTRVAL 2048 |
| #define | SZ_FNAME 255 |
| #define | SZ_XMLTAG 1024 |
| #define | SZ_LINE 4096 |
| #define | MAX_ATTR 100 |
| #define | HANDLE_INCREMENT 1024000 |
| #define | min(a, b) ((a<b)?a:b) |
| #define | max(a, b) ((a>b)?a:b) |
| #define | handle_t int |
| Handle type definition. | |
Typedefs | |
| typedef struct elem_t | Element |
| typedef struct node | Node |
Functions | |
| int | vot_attrSet (AttrBlock *ablock, char *name, char *value) |
| Set/Create an attributes (private method). | |
| char * | vot_attrGet (AttrBlock *ablock, char *name) |
| Get an attribute's value (private method). | |
| char * | vot_attrXML (AttrBlock *ablock) |
| Get the attributes for an XML tag (private method). | |
| int | vot_eType (char *name) |
| Get the integer value (ID) of the name (private method). | |
| char * | vot_elemName (Element *e) |
| Get the name of the Element (private method). | |
| int | vot_elemType (Element *e) |
| Get the integer value (ID) of the Element (private method). | |
| char * | vot_elemXML (Element *e) |
| Builds a string of the opening XML Tag (private method). | |
| char * | vot_elemXMLEnd (Element *e) |
| Build a string of the ending XML Tag (private method). | |
| Element * | vot_newElem (unsigned int type) |
| Allocate a new structure of the given type (private method). | |
| handle_t | vot_setHandle (Element *elem) |
| Assign the Element a handle_t (private method). | |
| handle_t | vot_lookupHandle (Element *elem) |
| Lookup the handle_t to an Element (private method). | |
| void | vot_freeHandle (handle_t handle) |
| Free a handle for use (private method). | |
| Element * | vot_getElement (handle_t handle) |
| Get the Element refered to by handle_t (private method). | |
| void | vot_newHandleTable (void) |
| Initialize a handle table (private method). | |
| int | vot_handleCount (void) |
| Get the number of handle_t used (private method). | |
| void | vot_handleCleanup (void) |
| Free all the handle nodes (private method). | |
| void | vot_handleError (char *msg) |
| Print an error message. | |
| void | vot_endElement (void *userData, const char *name) |
| CB whenever an end tag is seen (private method). | |
| void | vot_startElement (void *userData, const char *name, const char **atts) |
| CB whenever a start tag is seen (private method). | |
| void | vot_charData (void *userData, const XML_Char *s, int len) |
| Handle non-element character strings (private method). | |
| void | vot_startCData (void *userData) |
| Handle the start of CDATA strings (private method). | |
| void | vot_endCData (void *userData) |
| Handle the end of CDATA strings (private method). | |
| void | votPush (Stack *st, Element *elem) |
| Push a Node to the top of the stack (private method). | |
| Element * | votPop (Stack *st) |
| Return a Node from the top of the stack (private method). | |
| Element * | votPeek (Stack *st) |
| Peek at Element on top of the Stack (private method). | |
| Stack * | vot_newStack (void) |
| Makes a new stack (private method). | |
| int | vot_isEmpty (Stack *st) |
| Checks to see if the stack is empty (private method). | |
| void | vot_clearStack (Stack *st) |
| Clear the stack (private method). | |
| void | vot_printStack (Stack *st) |
| Print the name of all the stack elements (private method). |
VOTPARSEP.H -- Internal LIBVOTABLE definitions.
| char* vot_attrGet | ( | AttrBlock * | ablock, | |
| char * | name | |||
| ) |
Get an attribute's value (private method).
vot_attrGet -- Get an attribute's value (private method).
| *ablock | An AttrBlock to insert these attributes | |
| *name | A string that hold the name of an attribute |
| int vot_attrSet | ( | AttrBlock * | ablock, | |
| char * | name, | |||
| char * | value | |||
| ) |
Set/Create an attributes (private method).
***************************************************************************
Public Internal Methods. The procedures are used to implement the library, however are not part of the public interface.
vot_attrSet -- Set/Create an attributes (private method).
| ablock | An AttrBlock to insert these attributes. | |
| name | A string that hold the name of an attribute. | |
| value | A string that hold the value of an attribute. |
| char* vot_attrXML | ( | AttrBlock * | ablock | ) |
Get the attributes for an XML tag (private method).
vot_attrXML -- Get the attributes for an XML tag (private method).
| *ablock | An AttrBlock to insert these attributes |
| void vot_charData | ( | void * | user, | |
| const XML_Char * | s, | |||
| int | len | |||
| ) |
Handle non-element character strings (private method).
vot_charData -- Handle non-element character strings (private method)
| user | User data (not used) | |
| s | content string | |
| len | length of string |
| vot_clearStack | ( | Stack * | st | ) |
Clear the stack (private method).
vot_clearStack -- Clear the stack (private method)
| st | A pointer to a Stack |
| char* vot_elemName | ( | Element * | e | ) |
| int vot_elemType | ( | Element * | e | ) |
| char* vot_elemXML | ( | Element * | e | ) |
Builds a string of the opening XML Tag (private method).
vot_elemXML -- Builds a string of the opening XML Tag (private method)
| *e | A pointer to an Element |
| char* vot_elemXMLEnd | ( | Element * | e | ) |
Build a string of the ending XML Tag (private method).
vot_elemXMLEnd -- Build a string of the ending XML Tag (private method)
| *e | A pointer to an Element |
| void vot_endCData | ( | void * | user | ) |
Handle the end of CDATA strings (private method).
vot_endCData -- Handle the end of CDATA strings (private method)
| user | User data (not used) |
| void vot_endElement | ( | void * | user, | |
| const char * | name | |||
| ) |
CB whenever an end tag is seen (private method).
vot_endElement -- CB whenever an end tag is seen (private method)
| user | User data (not used) | |
| name | The name in the XML tag |
| int vot_eType | ( | char * | name | ) |
Get the integer value (ID) of the name (private method).
vot_eType -- Get the integer value (ID) of the name (private method).
| name | Name of the desired type |
| void vot_freeHandle | ( | handle_t | handle | ) |
Free a handle for use (private method).
vot_freeHandle -- Free a handle for use (private method)
| handle | A handle_t to the Element you wish to free |
| Element* vot_getElement | ( | handle_t | handle | ) |
| void vot_handleCleanup | ( | void | ) |
Free all the handle nodes (private method).
vot_handleCleanup -- Free all the handle nodes (private method)
| int vot_handleCount | ( | void | ) |
Get the number of handle_t used (private method).
count of current used handles vot_handleCount -- Get the number of handle_t used (private method)
| void vot_handleError | ( | char * | msg | ) |
Print an error message.
vot_handleError -- Print an error message.
| int vot_isEmpty | ( | Stack * | st | ) |
Checks to see if the stack is empty (private method).
vot_isEmpty -- Checks to see if the stack is empty (private method)
| st | A pointer to a Stack |
| handle_t vot_lookupHandle | ( | Element * | elem | ) |
| Element* vot_newElem | ( | unsigned int | type | ) |
| void vot_newHandleTable | ( | void | ) |
Initialize a handle table (private method).
vot_newHandleTable -- Initialize a handle table (private method)
| Stack * vot_newStack | ( | void | ) |
Makes a new stack (private method).
vot_newStack -- Makes a new stack (private method)
| vot_printStack | ( | Stack * | st | ) |
Print the name of all the stack elements (private method).
vot_printStack -- Print the name of all the stack elements (private method)
| st | A pointer to a Stack |
| handle_t vot_setHandle | ( | Element * | elem | ) |
| void vot_startCData | ( | void * | user | ) |
Handle the start of CDATA strings (private method).
vot_startCData -- Handle the start of CDATA strings (private method)
| user | User data (not used) |
| void vot_startElement | ( | void * | user, | |
| const char * | name, | |||
| const char ** | atts | |||
| ) |
CB whenever a start tag is seen (private method).
vot_startElement -- CB whenever a start tag is seen (private method)
| user | User data (not used) | |
| name | The name in the XML tag. | |
| atts | An array of attributes. |


Self-Hosted gBridge¶
Prerequisites¶
The following points need to be satisfied in order to host your own instance of gBridge.
- Availability of a (web-) server that is running constantly. Docker needs to be installed. A Raspberry Pi should have plenty of power for this purpose.
- A webserver is running, available and configured, one needs to be available to access it publicly. A static domain (e.g. provided by a DDNS provider) has to be configured for your server, too.
- Your webserver needs to be configured for HTTPS. A valid, signed certificate must be served via HTTPS. This should be no problem nowadays since one can get free certificates, e.g. from Let’s Encrypt.
- A MQTT server needs to available in your network.
Set up Google Action¶
This part will describe the process of creating a new Smart Home project in the Google Actions Console. Your new project will be listed as a smart home provider in the Google Home app, thus can be used in your own environment.
Create a new Project¶
Navigate to the Google Actions Console. Make sure you are logged in with the Google Account you are already using with Google Assistant.
Choose a name¶
Choose a generic name. Create the new project and select it to be a “Home control” application.
Set up account linking¶
- Do not allow users to register accounts via voice.
- Select OAuth only with Implicit grants.
- Generate a random password for the client id. Avoid special chars. This can be long and difficult to remember, since you only need to enter it once later on.
- Use the following URL:
https://YOUR-WEBSERVER'S-ADDRESS/gbrigde/gapi/auth
. For example:https://dev.gbridge.kappelt.net/gbrigde/gapi/auth
- OAuth scopes are not required, leave them empty. You don’t need to add a useful instruction for account linking either.
Add action fulfillment¶
- Go back to the overview page, select “Add Actions”.
- Enter the following URL as the fulfillment URL:
https://YOUR-WEBSERVER'S-ADDRESS/gbrigde/gapi
. For example:https://dev.gbridge.kappelt.net/gbrigde/gapi
Look for the project id¶
Note the project id, since it’ll be necessary to known it later. It is shown in the project settings.
Start simulator for synchronization¶
Select “Simulator” in the left menu. Choose your own language there, click on “Start Testing”. There is no need to do anything more here. This step is sometimes necessary for synchronization of the project options.
Enable the Homegraph API¶
- Navigate to the Google Cloud Console
- Select your project in the top bar. Select “APIs and Services” in the left menu.
- Add a new API. Search for “Homegraph”, select it and enable it afterwards.
- Open the left menu, select “APIs and Services”, “Credentials” there.
- Select “Create credentials”, “API Key”. Note the new key.
- For safety reasons, select “Restrict key”. Choose “HomeGraph API” as the only API restriction and save.
Set up gBridge in Docker¶
Prerequisites¶
Install both docker
and docker-compose
on your server, e.g. with your favourite package manager.
Generate Docker-Compose-File¶
A small script for generating individual Docker-Compose-Files for gBridge is available under https://about.gbridge.kappelt.net/dockergen.
Fill in your information. Since a webserver is probably already running on your server, make sure to select a webserver port that is free.
Click on “Generate and Download” to download your individual docker-compose file. Save it in an new, empty directory (e.g. /opt/gbridge/
) on your server:
sysop@kappelt:/opt/gbridge$ ls -al
insgesamt 12
drwxr-xr-x 2 root root 4096 Aug 12 12:11 .
drwxr-xr-x 5 root root 4096 Aug 12 12:10 ..
-rwxrwxrw-+ 1 sysop sysop 2176 Aug 12 12:09 docker-compose.yml
Starting gBridge for the first time¶
Navigate to the directory, run docker-compose up
. Depending on your account’s permissions, you might need to run this as the root user.
Docker is going to download the necessary packages. A lot of lines will be displayed. Look for the following ones, they usually indicate a successfull startup:
If you’ve chosen to use a docker database:
Creating gbridge_database_1 ... done
...
database_1 | GENERATED ROOT PASSWORD: ZZZZ
...
database_1 | MySQL init process done. Ready for start up.
...
database_1 | 2018-08-12T10:19:26.111095Z 0 [Note] Event Scheduler: Loaded 0 events
database_1 | 2018-08-12T10:19:26.112757Z 0 [Note] mysqld: ready for connections.
database_1 | Version: '5.7.23' socket: '/var/run/mysqld/mysqld.sock' port: 3306 MySQL Community Server (GPL)
If you’ve chosen to run Redis in docker:
cache_1 | 1:C 12 Aug 10:18:34.393 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
cache_1 | 1:C 12 Aug 10:18:34.395 # Redis version=4.0.11, bits=64, commit=00000000, modified=0, pid=1, just started
...
cache_1 | 1:M 12 Aug 10:18:34.400 * Ready to accept connections
Always shown:
redis-worker_1 | MQTT client connected
redis-worker_1 | Redis client (subscribe) connected
redis-worker_1 | Redis client (cache) connected
redis-worker_1 | Redis client (subscribe) successful subscribe to gbridge:u*:d*:*
...
web_1 | [Sun Aug 12 10:18:48.685014 2018] [mpm_prefork:notice] [pid 1] AH00163: Apache/2.4.25 (Debian) PHP/7.2.8 configured -- resuming normal operations
web_1 | [Sun Aug 12 10:18:48.685345 2018] [core:notice] [pid 1] AH00094: Command line: 'apache2 -D FOREGROUND'
If you got all lines and no obvious errors are visible, stop the containers by pressing Ctrl + C
once.
Start containers in background¶
..by running docker-compose up --detach
:
sysop@kappelt:/opt/gbridge$ docker-compose up --detach
Starting gbridge_database_1 ... done
Starting gbridge_cache_1 ... done
Starting gbridge_redis-worker_1 ... done
Starting gbridge_web_1 ... done
You can now view the container’s log files by navigating to gBridge’s directory and running docker-compose logs
.
To stop the containers, navigate into gBridge’s directory and run docker-compose stop
.
Prepare the database¶
Make sure the containers are running.
Navigate into gBridge’s directory, run docker-compose exec web php artisan migrate
. Type “yes” as a confirmation, enter your mail once prompted.
sysop@kappelt:/opt/gbridge$ sudo docker-compose exec web php artisan migrate
**************************************
* Application In Production! *
**************************************
Do you really wish to run this command? (yes/no) [no]:
> yes
Migration table created successfully.
Enter your E-Mail address<EMAIL_ADDRESS>A new user with the mail<EMAIL_ADDRESS>and the password "123456" has been created.
Please change the password immediately!
Migrating: 2014_10_12_000000_create_users_table
...
Open the web interface¶
Navigate to the docker host’s ip in your webbrowser, use the port you’ve entered for the web interface. In my case, the host’s IP address is <IP_ADDRESS>
and I’ve chosen the port 8080
.
You should see the login screen:
Log in using the mail you’ve entered during database setup and the password 123456
.
You should now see the empty account dashboard:
Warning
Immediately change your password under “Hi {YOUR-MAIL}”, “My Account”.
Configure your webserver¶
gBridge requires you to have an available webserver, that is publicly accessible. This part describes the configuration for this servers.
Apache 2¶
Your virtual host configuration can look similar to the following. Please note, that Apache’s proxy module has to be enabled (a2enmod proxy_http
).
<VirtualHost *:443>
#Leave this part as configured
#You'll still be able to use the webserver for your own services.
ServerAdmin<EMAIL_ADDRESS>DocumentRoot /var/www/html/
#Usually your public DNS name
ServerName dev.gbridge.kappelt.net
ServerAlias dev.gbridge.kappelt.net
#note that HTTPS is required
SSLEngine on
SSLCertificateFile /path/to/your/certificate.cer
SSLCertificateKeyFile /path/to/your/keyfile.key
SSLCertificateChainFile /path/to/your/fullchain.cer
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
#
#Proxying of gBridge-Requests
#
#the IP of the Docker host gBridge is running on
Define GBRIDGE_HOST localhost
#the port you've defined for the gBridge web interface
Define GBRIDGE_PORT 8080
ProxyPreserveHost On
ProxyRequests off
#note that public access for the account dashboard is disabled here due to security reasons
ProxyPass /gbridge/gapi http://${GBRIDGE_HOST}:${GBRIDGE_PORT}/gapi
ProxyPassReverse /gbridge/gapi http://${GBRIDGE_HOST}:${GBRIDGE_PORT}/gapi
</VirtualHost>
NGINX¶
Your NGINX-Config may look similar to this.
Note
This configuration hasn’t been tested before, since I’m not using NGINX on my servers. I’d appreciate feedback, whether this config is OK.
server {
listen 443 ssl;
#usually your public DNS name
server_name dev.gbridge.kappelt.net;
#SSL-settings and generic server options here
#the IP of the Docker host gBridge is running on
set $gbridge_host localhost
#the port you've defined for the gBridge web interface
set $gbridge_port 8080
location /gbridge/gapi/ {
#public access to the account dashboard is disabled for security reasons
proxy_pass http://$gbridge_host:$gbridge_port/gapi/;
}
}
Test it¶
Access Test¶
Try to access https://YOUR-WEBSERVER'S-ADDRESS/gbridge/gapi
with your webbrowser. You should get this JSON-formatted text response:
{"requestId":"","payload":{"errorCode":"protocolError"}}
Navigate to https://YOUR-WEBSERVER'S-ADDRESS/gbridge/gapi/auth
with your webbrowser. You should see the account linking page:
Congratulations¶
Your gBridge instance should now work a treat!. You can continue with logging in in your Google Home account, have a look at the getting started chapter.


Start Jupyter Notebook with Visualisation File
If you followed the installation guide
to set set up the package and it is installed successfully, it is now also possible
to start the jupyter notebook to visualize the data after applying a PCA. How the PCA is
applied, please take a look at the documentation of leaf_cc.data_visualisation.run_pca()
.
If the package is cloned from git and set up with conda, it is possible to run the notebook from command line as follow. Please be sure that the current working directory is in the folder leaf_cc, which is ensured if you have followed the installation instructions.
$ jupyter notebook leaf_cc/notebooks/VisualWidget.ipynb
The second possibility is to run the model and activate the option to start the jupyter
notebook file by adding -n=True
to the running statement.
Please consider if you choose this option, the jupyter notebook file is called from the
package itself, so any modifications are applied into the file in the package.
$ $ leaf_cc-run_model -n=True
Once the statement is executed and the notebook appeared, all the cells should be restarted. How to do that, please refer to the Jupyter Notebook user guide.
The corresponding file should look like in this appended example.
To chose multiple species in the dropdown menu, CTRL
has to be pressed while clicking
on additional species for selecting.
After that, by pressing the Update
button, all the cells below are refreshed.


---
layout: post
title: stopping a page refresh
tags:
- browser
- JavaScript
status: publish
type: post
published: true
meta:
_edit_last: '2'
---
I found myself having to trap a user attempting to refresh a page for one of our web apps. After a little bit of digging I stumbled across this solution:
[code]
[/code]
To use it simply embed or include it into your template
Eventhough the article says this is a IE specific event/feature it also works in FireFox. You should be aware that whenever the user leaves the page, they will be prompted about their impeding data loss, which can get a little tedious while developing.
Again this became a handy feature for our AJAX apps as most of the processing is done in the background without the page reload, a user could accidentally hit the back button and loose where they were at.


--- title: New attack cracks common Wi-Fi encryption in a minute layout: post ---
The earlier attack, developed by researchers Martin Beck and Erik Tews, worked on a smaller range of WPA devices and took between 12 and 15 minutes to work. Both attacks work only on WPA systems that use the Temporal Key Integrity Protocol (TKIP) algorithm. They do not work on newer WPA 2 devices or on WPA systems that use the stronger Advanced Encryption Standard (AES) algorithm.
Time to upgrade your routers to use WPA2.


OpenID support for Relying Parties (aka Consumers).
This module documents the main interface with the OpenID consumer library. The only part of the library which has to be used and isn‘t documented in full here is the store required to create an Consumer instance.
The OpenID identity verification process most commonly uses the following steps, as visible to the user of this library:
The most important part of the flow to note is the consumer‘s site must handle two separate HTTP requests in order to perform the full identity check.
This consumer library is designed with that flow in mind. The goal is to make it as easy as possible to perform the above steps securely.
At a high level, there are two important parts in the consumer library. The first important part is this module, which contains the interface to actually use this library. The second is openid/store/interface.rb, which describes the interface to use if you need to create a custom method for storing the state this library needs to maintain between requests.
In general, the second part is less important for users of the library to know about, as several implementations are provided which cover a wide variety of situations in which consumers may use the library.
The Consumer class has methods corresponding to the actions necessary in each of steps 2, 3, and 4 described in the overview. Use of this library should be as easy as creating an Consumer instance and calling the methods appropriate for the action the site wants to take.
This library automatically detects which version of the OpenID protocol should be used for a transaction and constructs the proper requests and responses. Users of this library do not need to worry about supporting multiple protocol versions; the library supports them implicitly. Depending on the version of the protocol in use, the OpenID transaction may be more secure. See the OpenID specifications for more information.
The Consumer object keeps track of two types of state:
These two types of storage are reflected in the first two arguments of Consumer‘s constructor, session and store. session is a dict-like object and we hope your web framework provides you with one of these bound to the user agent. store is an instance of Store.
Since the store does hold secrets shared between your application and the OpenID provider, you should be careful about how you use it in a shared hosting environment. If the filesystem or database permissions of your web host allow strangers to read from them, do not store your data there! If you have no safe place to store your data, construct your consumer with nil for the store, and it will operate only in stateless mode. Stateless mode may be slower, put more load on the OpenID provider, and trusts the provider to keep you safe from replay attacks.
Several store implementation are provided, and the interface is fully documented so that custom stores can be used as well. See the documentation for the Consumer class for more information on the interface for stores. The implementations that are provided allow the consumer site to store the necessary data in several different ways, including several SQL databases and normal files on disk.
In the flow described above, the user may need to confirm to the OpenID provider that it‘s ok to disclose his or her identity. The provider may draw pages asking for information from the user before it redirects the browser back to the consumer‘s site. This is generally transparent to the consumer site, so it is typically ignored as an implementation detail.
There can be times, however, where the consumer site wants to get a response immediately. When this is the case, the consumer can put the library in immediate mode. In immediate mode, there is an extra response possible from the server, which is essentially the server reporting that it doesn‘t have enough information to answer the question yet.
Integrating this library into an application is usually a relatively straightforward process. The process should basically follow this plan:
Add an OpenID login field somewhere on your site. When an OpenID is entered in that field and the form is submitted, it should make a request to the your site which includes that OpenID URL.
First, the application should instantiate a Consumer with a session for per-user state and store for shared state using the store of choice.
Next, the application should call the begin method of Consumer instance. This method takes the OpenID URL as entered by the user. The begin method returns a CheckIDRequest object.
Next, the application should call the redirect_url method on the CheckIDRequest object. The parameter return_to is the URL that the OpenID server will send the user back to after attempting to verify his or her identity. The realm parameter is the URL (or URL pattern) that identifies your web site to the user when he or she is authorizing it. Send a redirect to the resulting URL to the user‘s browser.
That‘s the first half of the authentication process. The second half of the process is done after the user‘s OpenID Provider sends the user‘s browser a redirect back to your site to complete their login.
When that happens, the user will contact your site at the URL given as the return_to URL to the redirect_url call made above. The request will have several query parameters added to the URL by the OpenID provider as the information necessary to finish the request.
Get a Consumer instance with the same session and store as before and call its complete() method, passing in all the received query arguments and URL currently being handled.
There are multiple possible return types possible from that method. These indicate the whether or not the login was successful, and include any additional information appropriate for their type.
| SUCCESS | = | :success | Code returned when either the of the OpenID::OpenIDConsumer.begin_auth or OpenID::OpenIDConsumer.complete_auth methods return successfully. | |
| FAILURE | = | :failure | Code OpenID::OpenIDConsumer.complete_auth returns when the value it received indicated an invalid login. | |
| CANCEL | = | :cancel | Code returned by OpenIDConsumer.complete_auth when the user cancels the operation from the server. | |
| SETUP_NEEDED | = | :setup_needed | Code returned by OpenID::OpenIDConsumer.complete_auth when the OpenIDConsumer instance is in immediate mode and ther server sends back a URL for the user to login with. |
| session_key_prefix | [RW] |
Initialize a Consumer instance.
You should create a new instance of the Consumer object with every HTTP request that handles OpenID transactions.
session: the session object to use to store request information. The session should behave like a hash.
store: an object that implements the interface in Store.
Set the name of the query parameter that this library will use to thread the requested URL through an OpenID 1 transaction (for use when verifying discovered information). It will be appended to the return_to URL.
Set the name of the query parameter that this library will use to thread a nonce through an OpenID 1 transaction. It will be appended to the return_to URL.
Start the OpenID authentication process. See steps 1-2 in the overview for the Consumer class.
user_url: Identity URL given by the user. This method performs a textual transformation of the URL to try and make sure it is normalized. For example, a user_url of example.com will be normalized to example.com/ normalizing and resolving any redirects the server might issue.
anonymous: A boolean value. Whether to make an anonymous request of the OpenID provider. Such a request does not ask for an authorization assertion for an OpenID identifier, but may be used with extensions to pass other data. e.g. "I don‘t care who you are, but I‘d like to know your time zone."
Returns a CheckIDRequest object containing the discovered information, with a method for building a redirect URL to the server, as described in step 3 of the overview. This object may also be used to add extension arguments to the request, using its add_extension_arg method.
Raises DiscoveryFailure when no OpenID server can be found for this URL.
Start OpenID verification without doing OpenID server discovery. This method is used internally by Consumer.begin() after discovery is performed, and exists to provide an interface for library users needing to perform their own discovery.
service: an OpenID service endpoint descriptor. This object and factories for it are found in the openid/consumer/discovery.rb module.
Returns an OpenID authentication request object.
Returns a subclass of Response. The type of response is indicated by the status attribute, which will be one of SUCCESS, CANCEL, FAILURE, or SETUP_NEEDED.


Header
Nav
Section
Article
H1
H2
H3
Aside
Checkout the article to the left it talks about H1, H2, and H3 tags!
Footer


Introduction
Audience
The target audience of this document is a Twisted user who wants to deploy a significant amount of Twisted code in a re-usable, standard and easily configurable fashion. A Twisted user who wishes to use the Application framework needs to be familiar with developing Twisted servers and/or clients.
Goals
- To introduce the Twisted Application infrastructure.
- To explain how to deploy your Twisted application using
.tac
files andtwistd
- To outline the existing Twisted services.
Overview
The Twisted Application infrastructure takes care of running and stopping your application. Using this infrastructure frees you from from having to write a large amount of boilerplate code by hooking your application into existing tools that manage daemonization, logging, choosing a reactor and more.
The major tool that manages Twisted applications is a command-line utility
called twistd
. twistd
is cross platform, and is the
recommended tool for running Twisted applications.
The core component of the Twisted Application infrastructure is the twisted.application.service.Application
object — an
object which represents your application. However, Application doesn't provide
anything that you'd want to manipulate directly. Instead, Application acts as
a container of any Services
(objects implementing IService
) that your application
provides. Most of your interaction with the Application infrastructure will be
done through Services.
By Service
, we mean anything in your application that can be started
and stopped. Typical services include web servers, FTP servers and SSH
clients. Your Application object can contain many services, and can even
contain structured hierarchies of Services using IServiceCollection
s.
Here's a simple example of constructing an Application object which represents an echo server that runs on TCP port 7001.
1 2 3 4 5 6 7 8 9 10 11
from twisted.application import internet, service from somemodule import EchoFactory port = 7001 factory = EchoFactory() # this is the important bit application = service.Application("echo") # create the Application echoService = internet.TCPServer(port, factory) # create the service # add the service to the application echoService.setServiceParent(application)
See Writing Servers for an explanation of EchoFactory.
This example creates a simple hierarchy:
application | `- echoServiceMore complicated hierarchies of services can be created using IServiceCollection. You will most likely want to do this to manage Services which are dependent on other Services. For example, a proxying Twisted application might want its server Service to only start up after the associated Client service.
Using application
twistd and tac
To handle start-up and configuration of your Twisted application, the
Twisted Application infrastructure uses .tac
files.
.tac
are Python files which configure an Application
object and assign this
object to the top-level variable
.application
The following is a simple example of a .tac
file:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
# You can run this .tac file directly with: # twistd -ny service.tac """ This is an example .tac file which starts a webserver on port 8080 and serves files from the current working directory. The important part of this, the part that makes it a .tac file, is the final root-level section, which sets up the object called 'application' which twistd will look for """ import os from twisted.application import service, internet from twisted.web import static, server def getWebService(): """ Return a service suitable for creating an application object. This service is a simple web server that serves files on port 8080 from underneath the current working directory. """ # create a resource to serve static files fileServer = server.Site(static.File(os.getcwd())) return internet.TCPServer(8080, fileServer) # this is the core part of any tac file, the creation of the root-level # application object application = service.Application("Demo application") # attach the service to its parent application service = getWebService() service.setServiceParent(application)
twistd
is a program that runs Twisted applications using a
.tac
file. In its most simple form, it takes a single argument
-y
and a tac file name. For example, you can run the above server
with the command twistd -y service.tac
.
By default, twistd
daemonizes and logs to a file called
twistd.log
. More usually, when debugging, you will want your
application to run in the foreground and log to the command line. To run the
above file like this, use the command twistd -noy
service.tac
For more information, see the twistd
man page.
Customizing twistd
logging
twistd
logging can be customized using the command
line. This requires that a log observer factory be
importable. Given a file named my.py
with the code:
1 2 3 4
from twisted.python.log import FileLogObserver def logger(): return FileLogObserver(open("/tmp/my.log", "w")).emit
invoking twistd --logger my.logger ...
will log
to a file named /tmp/my.log
(this simple example could easily be
replaced with use of the --logfile
parameter to twistd).
Alternatively, the logging behavior can be customized through an API
accessible from .tac
files. The ILogObserver
component can be
set on an Application in order to customize the default log observer that
twistd
will use.
Here is an example of how to use DailyLogFile
, which rotates the log once
per day.
1 2 3 4 5 6 7
from twisted.application.service import Application from twisted.python.log import ILogObserver, FileLogObserver from twisted.python.logfile import DailyLogFile application = Application("myapp") logfile = DailyLogFile("my.log", "/tmp") application.setComponent(ILogObserver, FileLogObserver(logfile).emit)
invoking twistd -y my.tac
will create a log file
at /tmp/my.log
.
Services provided by Twisted
Twisted provides several services that you want to know about.
Each of these services (except TimerService) has a corresponding
connect
or listen
method on the reactor, and the constructors for
the services take the same arguments as the reactor methods. The
connect
methods are for clients and the listen
methods are for
servers. For example, TCPServer corresponds to reactor.listenTCP and TCPClient
corresponds to reactor.connectTCP.
TCPServer
TCPClient
- Services which allow you to make connections and listen for connections on TCP ports.
UNIXServer
UNIXClient
- Services which listen and make connections over UNIX sockets.
SSLServer
SSLClient
- Services which allow you to make SSL connections and run SSL servers.
UDPServer
UDPClient
- Services which allow you to send and receive data over UDP
See also the UDP documentation.
UNIXDatagramServer
UNIXDatagramClient
- Services which send and receive data over UNIX datagram sockets.
MulticastServer
- A server for UDP socket methods that support multicast.
TimerService
- A service to periodically call a function.
Service Collection
IServiceCollection
objects contain
IService
objects.
IService objects can be added to IServiceCollection by calling setServiceParent
and detached
by using disownServiceParent
.
The standard implementation of IServiceCollection is MultiService
, which also implements
IService. MultiService is useful for creating a new Service which combines two
or more existing Services. For example, you could create a DNS Service as a
MultiService which has a TCP and a UDP Service as children.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
from twisted.application import internet, service from twisted.names import server, dns, hosts port = 53 # Create a MultiService, and hook up a TCPServer and a UDPServer to it as # children. dnsService = service.MultiService() hostsResolver = hosts.Resolver('/etc/hosts') tcpFactory = server.DNSServerFactory([hostsResolver]) internet.TCPServer(port, tcpFactory).setServiceParent(dnsService) udpFactory = dns.DNSDatagramProtocol(tcpFactory) internet.UDPServer(port, udpFactory).setServiceParent(dnsService) # Create an application as normal application = service.Application("DNSExample") # Connect our MultiService to the application, just like a normal service. dnsService.setServiceParent(application)


On July 20, 2019, Dimension CTO Yisi Liu was invited to speak at DWeb Camp 2019.
About DWeb Camp
DWeb Camp is located on a farm above the Pacific Ocean. In an elegant and beautiful environment, I hope to gather more people for deeper communication.
DWeb Camp is a diverse place where more people can freely exchange technology, laws, markets, agreements, ideas, etc, allowing people to build deep connections.
DWeb Camp has established a good relationship with the builders of Web 3.0, and at the same time has established interaction and close contact with the global high-quality technology community. DWeb also calls on more communities to participate together. It’s a community-built event, just come and tell us: “What can you share?”
For those who want to create a more open, private, secure, and fun Web, DWeb Camp is a permanently open decentralized network.
DWeb Camp Origins
In 1994, Tim Berners-Lee created the World Wide Web, which became the core of the development of the information age. Today it has become the world’s most powerful knowledge, communication and business medium, but that does not mean that Tim Berners-Lee is happy with all the consequences.
“It controls what people see, creates mechanisms for how people interact, It’s been great, but spying, blocking sites, repurposing people’s content, taking you to the wrong websites – that completely undermines the spirit of helping people create.”
Therefore, in June 2016, Tim Berners-Lee and other top computer scientists gathered at the first Decentralized Web Summit in San Francisco, including Brewster Kahle, the head of the non-profit organization Internet Archive. which posed a new challenge to early Internet developers:
let’s use decentralized technologies to ‘Lock the Web Open’
The purpose of the 2016 gathering is to call on everyone to build a better network
DWeb’s achievements were shown at the 2018 Decentralized Web Summit – Global Visions/Working Code conference. With so much prototyping and application built on decentralized protocols, it’s time to collaborate, communicate and interact with the communities that need these tools most.
DWeb Camp 2019
DWeb Camp 2019 was held on July 18-21, 2019 in Pescadaro, California. The conference was sponsored by Interner Archive, Ford Foundation and Prorocal Labs. Web 3, Ethereum Foundation, Blockstack, Orchid and other well-known institutions participated Among them, we spent four days together on a beautiful Internet imagination journey.
DWeb Camp 2019 attracted top Internet developers from all over the world to participate in this gathering. The World Wide Web founder Tim Berners Lee, IPFS founder Juan Benet, Cosmos engineer Han Schoenburg, Gun founder Mark Nadal, etc. were all present.
Yisi Liu live lecture video
Topic of speech
Distributed Identity Privacy
Speech content
Yisi Liu introduces current privacy issues and then analyzes why privacy is so important to us and why privacy is violated. He gave examples of data leaks on Facebook, Equifax, and WeChat. Here we can see that our data has been collected and abused by various platforms, and our privacy has been violated and abused without our knowledge. We are being monitored anytime, anywhere.
Yisi Liu also analyzed the current solutions for data breaches, including password management tools and OpenID. But these solutions have not completely solved the hidden dangers of data leakage.
Given the current situation, Yisi Liu proposed a idea, which differs from the existing schemes, namely distributed identity privacy. Yisi Liu explained that distributed identity privacy is that digital identities are created by users themselves, can be authenticated by a third party, and have enough credit to prove identity reliability. Users can freely choose to share different information on different platforms, and have ownership and use rights of data.
By separating user accounts from passwords, users can use the same password to participate in all services or products that support password pairs. A new social network was formed.
Because each identity is stored in the distributed ledger, every new identity authentication is publicly updated in the distributed ledger. Therefore, Yisi Liu believes that the credit of this scheme comes from the foundation of the distributed ledger itself, and is a kind of mathematical-based credit.
Finally, Yisi Liu introduced the company’s product—— Maskbook, which is a browser encryption plug-in designed based on distributed identity privacy.
Each user generates or reuses a unified identity (secp256k1 password pair) and connects it to their Facebook account. This allows users to encrypt content they post, and even Facebook developers cannot view the content.
Scene photos
Event Page: https://dwebcamp.org/
Github https://github.com/DimensionDev
Twitter https://twitter.com/realMaskNetwork
Facebook https://www.facebook.com/masknetwork
Discord https://discord.com/invite/cKGW45g
Telegram (English) https://t.me/maskbook_group
Telegram （中文） https://t.me/masknetwork_cn


OneWord
Home
Your OneWord
About
Contact
OneWord
Home
What OneWord is...
OneWord is a website that allows you to create a playlist based one a single word. Give it a try!
Create a Playlist!
View Your OneWord!


Our website uses an interactive methodology of teaching Maths using the latest web technologies. Your learning experience with us is guaranteed to be intuitive and fun. You will have fun while learning. This is the secret of our outstanding results. Check reviews from our students.


This is the index page of GitHub issues bot. For information about usage, see Operation modes - Web app below.
To get started quickly:
/callback
webhook secret
auth.cfg
ahoj


Infinite list of inspiring and self education videos from all over the web
Promoting technology and innovation
Slack brings all your communication together in one place. It's real-time messaging.
Look at peoples profiles and stuff


HTML to JS
Convert HTML structures to JS code generating them.
Input
Output
Remove whitespace
Append to DocumentFragment


@dothanhlam
Lam Do
Ho Chi Minh City, Vietnam
@dothanhlam
http://dothanhlam.wordpress.com
https://github.com/dothanhlam
a programming paradigm
often abbreviated FP
using function
Just starting from scratch
Don't relearn anything
Forget Everything You Know
Pure functions
Function composition
Shared state
Side effects
Immutability
Produce the same output given the same inputs
Has no side-effects
Combining two or more functions to make a new function
State which is shared between more than one function
Something changes somewhere you don't know
Pure functions have no side effects
An immutable object is an object that can’t be modified after it’s created
FP has no variables
Imperative - the flow control describes "How to do"
Declarative - the data flow describes "What to do"
the program logic is expressed without explicitly describing the flow control


Rivers are a major source of plastic waste into oceans
It is estimated that between 1.15 and 2.41 million metric tonnes of plastic currenty enters the ocean every year via rivers, with 86% of this global input coming from Asia.
Click on the polluted beach and recycling icons to discover more facts about which countries consume the most plastic per person and some sample recycling statistics


All submissions for this problem are available.
Jamoora is a microbiologist. Unfortunately, there has been an outbreak of plague in his hometown. Plague is being spread by mice which are currently N in number and they increase every day by R% through reproduction(obviously). Number of mice remaining is rounded down to nearest integer after each day. Also, due to resource constraints Jamoora can only remove a constant number of mice S every day in the morning. Jamoora has received order from his government that he must eradicate the plague within D days. Your task is to help Jamoora by finding the minimum number S that successfully eradicates the plague in D days.
Input:
First line will contain T, number of testcases. Then the testcases follow. Each testcase contains of a single line of input, three space seperated integers N, R, D .
Output:
For each testcase, output minimum S that successfully eradicates the plague in D days.
Constraints
1≤T≤10
2≤N≤2×109
1≤R≤105
1≤D≤104
Sample Input:
1
1000 50 5
Sample Output:
384
EXPLANATION:
In the above case, the set amount of rats to be removed everyday(the solution) is 384. On the first day after removal 616 rats are left, which after reproduction becomes 924. Similarly, for further days, number of rats become,
Day 2: 540 & 810,
Day 3: 426 & 639,
Day 4: 255 & 382,
Day 5: 0 and 0.
Thus, plague is eradicated on the fifth day.


Package com.lambdaschool.schools.models
Class Telephone
- java.lang.Object
-
- com.lambdaschool.schools.models.Instructor
-
@Entity public class Telephone extends java.lang.Object
The entity allowing interaction with the instructors table
-
-
Field Summary
Fields Modifier and Type Field Description protected java.lang.String
createdBy
String field containing the username of who created this rowprotected java.util.Date
createdDate
Date field containing the date and time when the row was createdprotected java.lang.String
lastModifiedBy
String field containing the username of who last modified this rowprotected java.util.Date
lastModifiedDate
Date field containing the data and time when the row was last modified
-
Constructor Summary
Constructors Constructor Description Telephone()
Default Constructor used primarily by the JPA.Telephone(TelephoneType phonetype, java.lang.String phonenumber, Zoo course)
Given the phone type, telephone number, and course object
-
Method Summary
All Methods Instance Methods Concrete Methods Modifier and Type Method Description long
getPhoneid()
Getter for the phone idjava.lang.String
getPhonenumber()
the telephone numberTelephoneType
getPhonetype()
Getter for the telephone number typeZoo
getZoo()
Getter for coursevoid
setPhoneid(long phoneid)
Setter for the phone idvoid
setPhonenumber(java.lang.String phonenumber)
Setter for the telephone numbervoid
setPhonetype(TelephoneType phonetype)
Setter for the telephone type of this telephone numbervoid
setZoo(Zoo course)
Setter for course
-
-
-
Field Detail
-
createdBy
protected java.lang.String createdBy
String field containing the username of who created this row
-
createdDate
protected java.util.Date createdDate
Date field containing the date and time when the row was createdTemporal(TIMESTAMP) - Sets the precision of the date being saved. In this case Date and Time
-
lastModifiedBy
protected java.lang.String lastModifiedBy
String field containing the username of who last modified this row
-
lastModifiedDate
protected java.util.Date lastModifiedDate
Date field containing the data and time when the row was last modifiedTemporal(TIMESTAMP) - Sets the precision of the date being saved. In this case Date and Time
-
-
Constructor Detail
-
Telephone
public Telephone()
Default Constructor used primarily by the JPA.
-
Telephone
public Telephone(TelephoneType phonetype, java.lang.String phonenumber, Zoo course)
Given the phone type, telephone number, and course object- Parameters:
phonetype
- The type of this phone number (String) or enumerated type of TelephoneType (Stretch goal)phonenumber
- The telephone (String) in any formatcourse
- The course object (Zoo) of this telephone
-
-
Method Detail
-
getPhoneid
public long getPhoneid()
Getter for the phone id- Returns:
- The primary key (long) for this telephone number
-
setPhoneid
public void setPhoneid(long phoneid)
Setter for the phone id- Parameters:
phoneid
- The new primary key (long) for this telephone number
-
getPhonetype
public TelephoneType getPhonetype()
Getter for the telephone number type- Returns:
- The type of this phone number (String) or enumerated type of TelephoneType (Stretch goal)
-
setPhonetype
public void setPhonetype(TelephoneType phonetype)
Setter for the telephone type of this telephone number- Parameters:
phonetype
- The new type of this phone number (String) or enumerated type of TelephoneType (Stretch goal)
-
getPhonenumber
public java.lang.String getPhonenumber()
the telephone number- Returns:
- the telephone number (String) any format allowed
-
setPhonenumber
public void setPhonenumber(java.lang.String phonenumber)
Setter for the telephone number- Parameters:
phonenumber
- the new telephone number (String) any format allowed
-
getZoo
public Zoo getZoo()
Getter for course- Returns:
- A full Zoo object of the course who is assigned this telephone number
-
setZoo
public void setZoo(Zoo course)
Setter for course- Parameters:
course
- The new full Zoo object of the course to assigned to this telephone number
-
-


2013 Exhibitors
General and exhibitor registration for SkeptiCal 2014 is open! If your group or organization is of interest to skeptics, please consider attending as an exhibitor this year. Please contact Tucker Hiatt for details.
Current Exhibitors:
Bay Area Skeptics
The Bay Area Skeptics encourage critical thinking and accuracy in media and in our schools.
Camp Quest West
A summer camp for children in non-religious families, with two locations in California and a dozen more nationwide.
Center For Inquiry
CFI fosters a secular society based on science, reason, freedom of inquiry, and humanist values.
Dan Riley / Generation Atheist
During his work from 2008-2011 at CFI, Dan Riley got to know many secular student leaders and decided to write Generation Atheist to tell their compelling personal journeys to atheism.
Dr. Ken Croswell
Astronomer Ken Croswell is author of eight books, including Planet Quest, Magnificent Mars, Ten Worlds, and The Lives of Stars.
East Bay Skeptics Society
EBSS is devoted to the advancement of reason, science, and intellectual integrity—and to the exposure of superstition, fraud, and pseudoscience.
Guerilla Skepticism
The Guerrilla Skepticism editing team improves skeptical content on Wikipedia by providing noteworthy citations and by removing unsourced claims from paranormal pages.
Independent Investigations Group
IIG administers a $50,000 prize for demonstrating paranormal abilities.
National Center for Science Education
The NCSE is a nonprofit member organization providing information and resources for schools, parents, and concerned citizens working to keep evolution and climate science in public science education.
Picturoo
Picturoos are tangible personalized photo products whose SkeptiCal proceeds will be shared with Wonderfest, the Bay Area Beacon of Science.
Physics Circus and Sidewalk Science
The Physics Circus presents fascinating science demonstrations to dazzle the imagination and inspire understanding, and Sidewalk Science brings physics displays to sidewalks around the City.
Reason For Reason
Reason 4 Reason advocates for skeptical activism.
Sacramento Area Skeptics
Promoting science, critical thinking and skepticism in the Sacramento area.
Secular Coalition for California
The California state chapter of Secular Coalition for America works to protect the secular character of state governments through coordinated state lobbying activities.
Secularity Clothing
Secularity Clothing is an independent clothing brand from the Bay Area that focuses on promoting secular values, heroes of science, and compassionate living.
Wonderfest, the Bay Area Beacon of Science
Wonderfest is a nonprofit corporation dedicated to science popularization and education.


Hello,
first thanks for providing KNIME 2.9 with additional features.
I did the update yesterday and had the following behaviour regarding memory handling with Stanford Tagger node on a rather small corpus (17 documents)
Version 2.8: works fine
Version 2.9: much slower and ends up with
ERROR Stanford tagger Execute failed: java.util.concurrent.ExecutionException: java.lang.OutOfMemoryError: Java heap space
Both same knime.ini
-XX:MaxPermSize=512m
I even doubled to 1024m, but same error message.
I reverted back to 2.8 and it works fine again.
Thanks for any help
Bernd


|
ECS160Android
FortNitta Android platform team
|
Public Member Functions | |
| CGameState () | |
| The GameState object is created in by the Game class before a match has actually started So this constructor just prepares some default values CGameState::Init() will set up the Game State object for an actual match. | |
| final void | Reset () |
| final CTerrainMap | TerrainMap () |
| final void | TerrainMap (CTerrainMap terrain_map) |
| final CConstructionMap | ConstructionMap () |
| final CUnits | Units () |
| final void | SetAIDifficulty (EAIDifficulty difficulty) |
| AI Settings. | |
| final EAIDifficulty | getAIDifficulty () |
| Gets the AI Difficulty. | |
| final EPlayerColor | GetMainPlayerColor () |
| final CPlayer | GetPlayerWithColor (EPlayerColor color) |
| final void | SetWind (CWind.EWindType type) |
| final ArrayList< CPlayer > | GetPlayersWithOwnedCastles (CGame game) |
| pointer to animation object we may want to make this a vector later on // // CAnimations* DAnimations; | |
Public Attributes | |
| String | DUsername |
| int | DTimeStep |
| CRandomNumberGenerator | DRandomNumberGenerator = new CRandomNumberGenerator() |
| ArrayList< CPlayer > | DPlayers = new ArrayList<CPlayer>() |
| java.util.ArrayList< CAnimation > | DAnimations = new java.util.ArrayList<CAnimation>() |
| java.util.ArrayList< CCannonball > | DCannonballs = new java.util.ArrayList<CCannonball>() |
| CWind | DWind = new CWind() |
| boolean | DIsNetworkUpdate |
| True if the network is updating. More... | |
| CTimer | DTimer = new CTimer() |
| boolean game.CGameState.DIsNetworkUpdate |
True if the network is updating.


CindyJS: Taylor series of complex functions
On the left, a phase portrait of a complex function is displayed.
On the right, one can see the approximation of the function through it's Taylor polynomials at the red base
point.
The complex function, the base point, the order of the polynomial and the zoom can be modified.


| Home | Trees | Index | Help |
|
|---|
| Package session2 :: Module SessionManager :: Class SessionManager |
|
A persistent session manager for Quixote.
| Method Summary | |
|---|---|
__init__ takes a session store instance and (optionally) the session class to use for storing session information. | |
__repr__(self)
| |
Clear any residual session information for this request. | |
Expire the current session, ie. | |
Called near the end of a failed request (i.e. | |
Called near the end of each successful request. | |
() -> Session | |
(session_id : string) -> boolean | |
(must_exist : boolean = false) -> bool | |
(session : Session) -> bool | |
(id : string) -> Session | |
Remove the session cookie from the remote user's session by resetting the value and maximum age in the response object. | |
(session_id : string) | |
Called near the beginning of each request: after the HTTPRequest object has been built, but before we traverse the URL or call the callable object found by URL traversal. |
| Class Variable Summary | |
|---|---|
int |
ACCESS_TIME_RESOLUTION = 1 |
| Method Details |
|---|
__init__(self,
store_obj,
session_class=<class session2.Session.Session at 0x4034b1ac>)
|
clear_session(self, request)Clear any residual session information for this request. |
expire_session(self)Expire the current session, ie. revoke the session cookie from the client, remove the session object from the current request, and list it for permanent removal. |
finish_failed_request(self)Called near the end of a failed request (i.e. a exception that was not a PublisherError was raised. |
finish_successful_request(self)Called near the end of each successful request. Not called if there were any errors processing the request. |
get_session(self)() -> Session Fetch or create a session object for the current session, and return it. If a session cookie is found in the HTTP request object, use it to look up and return an existing session object. If no session cookie is found, create a new session. Note that this method does not cause the new session to be stored in the session manager, nor does it drop a session cookie on the user. Those are both the responsibility of finish_successful_request(). |
has_session(self, session_id)(session_id : string) -> boolean Return true if a session identified by 'session_id' exists in the session manager. |
has_session_cookie(self, must_exist=False)(must_exist : boolean = false) -> bool Return true if the request already has a cookie identifying a session object. If 'must_exist' is true, the cookie must correspond to a currently existing session; otherwise (the default), we just check for the existence of the session cookie and don't inspect its content at all. |
maintain_session(self, session)(session : Session) -> bool Maintain session information. This method is called after servicing an HTTP request, just before the response is returned. If a session contains information a cookie is dropped on the client and True is returned. If not, the session is forcibly expired and False is returned. |
new_session(self, id)(id : string) -> Session Return a new session object, ie. an instance of the session_class class passed to the constructor (defaults to Session). |
revoke_session_cookie(self)Remove the session cookie from the remote user's session by resetting the value and maximum age in the response object. Also remove the cookie from the request so that further processing of this request does not see the cookie's revoked value. |
set_session_cookie(self, session_id)(session_id : string) Ensure that a session cookie with value 'session_id' will be returned to the client via the response object. |
start_request(self)Called near the beginning of each request: after the HTTPRequest object has been built, but before we traverse the URL or call the callable object found by URL traversal. |
| Class Variable Details |
|---|
ACCESS_TIME_RESOLUTION
|
| Home | Trees | Index | Help |
|
|---|
| Generated by Epydoc 2.1 on Sat Feb 4 16:40:10 2006 | http://epydoc.sf.net |


Examples can be found in src/
Change the imported example in index.ts or replace it with your own code.
Errors will be displayed in this window, for output open the console below.


org.jclouds.vcloud.director.v1_5.features.admin
Classes
AdminCatalogAsyncClient
AdminCatalogClient
AdminNetworkAsyncClient
AdminNetworkClient
AdminOrgAsyncClient
AdminOrgClient
AdminQueryAsyncClient
AdminQueryClient
AdminVdcAsyncClient
AdminVdcClient
GroupAsyncClient
GroupClient
UserAsyncClient
UserClient


I would love to help you come up with strageties for customer retention/customer success or act as a second pair of hands for whatever project you are working on.


PENCHAL NETWORK
PENCHAL NETWORK is the DATA-NETWORK consist of Huge And Large iNTERNET eBooks Collections by PENCHAL...
Profile @ Glance
Will be Updated Sooooooon....


Javascript Guidelines
Coding and naming convention style guidelines make your code clearer, easier to read and, they can also actually improve performance.
Although you can use any convention that makes sense for you, the guidelines described here are based on years of experience from SproutCore developers in writing understandable and maintainable code.
The SproutCore coding and naming convention style guidelines are based on the Cocoa style guide from CocoaDevCentral.
1 - Classes
Although JavaScript is a prototype-based language, SproutCore overlays the some of the concepts of traditional class-based programming for ease of use.
1.1 - Defining Classes
Just as with Objective-C, JavaScript and thus, SproutCore, is not natively name spaced. Therefore, it is very important to be careful to use a consistent prefix when naming your classes. When you create a SproutCore application using the build tools, it will automatically set up a name space variable for you in core.js in your project.
For example, if you are writing an application called "AddressBook", the build tools will create the following:
"apps/address_book/core.js"AddressBook = SC.Application.create({ // ... });
In SproutCore, class names are always capitalized. If you are extending an existing SproutCore view, it is generally preferred to add the name of the view to the end of the class name. For instance, if you extend a CollectionView in your AddressBook application to show a list of Contact objects, you would do it in the following manner:
AddressBook.ContactCollectionView = SC.CollectionView.extend({
// Add your custom properties and functions here.
});
1.2 - Instantiated Classes
If you are creating an instantiated SproutCore class, such as a controller, the naming convention is slightly different. An instantiated class is named using camel case with the first letter lowercase. If you're creating an ArrayController to control your Contact objects, you would do the following:
AddressBook.contactsController = SC.ArrayController.create({
// Add your custom properties and functions here.
});
1.3 - Create vs Extend and Design
You may have noticed that the first two examples use .create() and the third uses .extend(). When should you use one of the other?
When you use .create(), you are creating an instance of a class. It is similar to using the new operator. On the other hand, when you use .extend(), the resulting object is created as a new a subclass, where the properties and functions from the base class are added in addition to the things that you define on your own.
.design() is essentially the same as .extend(). It allows Greenhouse and the SproutCore design framework to create parallel classes that can be used to manipulate views at design time. Unless you're including the design framework, .design() works the same as .extend().
2 - Properties and Variables
Descriptive property and variable names are strongly encouraged in SproutCore. Since most deployed applications will deliver the JavaScript compressed to the user, using terse names will not significantly reduce the amount sent over the wire. Also, if any obfuscation is used as part of the build process, it will optimize the names for you. Therefore, naming your variables or properties as descriptive as you need will make the life of the developer a lot better and not degrade performance or the user experience.
All properties and variable names are camel case with the first letter lower case. The name should describe what the variable or property contains. It is not necessary to indicate the type of a variable in the name. For example, you don't need to name a variable meant to store a string myString or an array variable myArray, but it is useful to name them in such a way that it is obvious anyway.
The only exceptions are booleans. When naming a boolean, it is recommended that you prefix them with is or isNot. Therefore, it is easy to determine in which manner they are to be used.
isEnabled: true, // This is good.
enabled: true // This is possibly confusing.
2.1 - Properties
A property is a variable that is directly defined on an object or class. These properties can be either public or private. Since JavaScript has no actual concept of private properties, the concept is merely to help developers. A private property name is prefixed with a underscore. In the following example of the contactController, there are two properties, first there is property called contactsList that is a public array containing the list of contacts, and then there is a private property called _contactsCount for internal book keeping. No matter if the property is static or if it is a computed property (which is actually a function), the naming convention is the same.
AddressBook.contactsController = SC.ArrayController.create({
_contactsCount: 0, // This is a private variable.
// This is a public variable. Access using get() and set()
contactsList: []
});
To access or modify public properties inside or outside the object, *always* use the get and set functions on the object, i.e.: this.get('contacts'). For private properties, always access them directly (i.e., this._contactsCount = 23;) If you find yourself accessing private variables from other objects, make them public and use get and set to access them. You can also use the getPath and setPath functions if you need to access/set a deeper property. This is not as fast, but it can make your code more readable.
2.2 - Variables
Variables are internal to a function only. Since it is local to that function, it is not encouraged to use an underscore as a prefix.
JavaScript will allow you to reference any variable name, even if you have not declared it before. If you reference a variable without declaring it first, however, the variable will be treated as a "global" variable, accessible to every function in your application. Since SproutCore applications are often very complex, it is important that you always use the var statement to declare your local variables first. Otherwise you may introduce bugs inadvertently. Mistakenly defining something outside of its scope is a typical error that can be very difficult to debug.
In addition, local variables are the fastest way of storing data in JavaScript. Making extensive use of local variables will get the best performance out of your code.
For example, in this function, count is a local variable:
countContacts: function(){
var count = 0; // This is local.
}
However, in this function, count is not a local variable, but rather a global variable defined in the window scope:
countContacts: function(){
count = 0; // This is NOT local, and VERY BAD.
}
2.2.1 - Optimizing the use of variables
When you access a property defined on an object multiple times, it is encouraged to store it locally inside the function. For instance, if you have a function that gets content of a view, collects some information from the record and then returns a string with all of the values combined. The first example is not efficient because there are many unnecessary function calls. Not only that, it is also hard to read! The second example pulls the content object into a local variable, contact and constructs the string with far fewer function calls and with far superior readability to boot.
This is confusing and inefficient:
constructName: function(){
return [this.get('content').get('prefix'),
this.get('content').get('firstName'),
this.get('content').get('middleName'),
this.get('content').get('lastName'),
this.get('content').get('suffix')].join(' ');
}
This is more readable and far faster since the commonly accessed property is saved locally:
constructName: function(){
var contact = this.get('content');
// This is more readable and far faster.
return [contact.get('prefix'),
contact.get('firstName'),
contact.get('middleName'),
contact.get('lastName'),
contact.get('suffix')].join(' ');
}
This is best (using the getEach function):
constructName: function(){
// This is EVEN more readable.
return this.get('content')
.getEach('prefix','firstName','middleName',
'lastName','suffix')
.join(' ');
}
Another strategy that often works well is to declare all of your local variables at the beginning of your method. The YUI compressor recommends declaring all variables on one line, like:
var a, b, x, obj;
3 - Functions
This is perhaps where the naming and coding style guidelines for SproutCore deviate the most from Objective-C. The reason is that the syntactic sugar is very different between Objective-C and JavaScript.
For SproutCore applications, the naming conventions are more or less the same as those used to name properties. Just as with properties, private functions on objects are prefixed with an underscore. The name of a function should be descriptive and give a sense of what purpose it is intended to perform.
This, however, is not a blank check to make a function name a full sentence. Naming a function constructContactFullNameWithPrefixAndSuffixString is not helping anyone, especially you, the developer. The specifics can be captured in the documentation. Instead, naming the function constructName gives a hint at what the function does and is not exceedingly verbose.
3.1 - Observers
If you are creating a function that serves as an observer, it is not required, but strongly encouraged to add the DidChange suffix to the name. Also, if the observer function is only observing one property, it is nice to name it after the name of the observed property. Below is an observer function observing the isSelected boolean property of a view:
isSelectedDidChange: function(){
// Do stuff based on selection.
}.observes('isSelected')
If you are observing more than one property, it is not useful to name the function after all the properties. In this case, naming the observer function after the first observed property is acceptable but it is also okay to name it something descriptive that hints at what happens in the function when it is triggered. For example, if you are observing multiple properties, such as content, isSelected, and dimensions and when any of those change, a redraw of your view will be triggered, you can name it as such:
redrawStateDidChange: function(){
this.displayDidChange(); // Redraw the view.
}.observes('content', 'isSelected', 'dimensions')
3.2 - Bindings
Bindings are special properties that will connect together the values of two objects in your application. Unlike most parts of SproutCore, you must follow a very specific formula for bindings to work properly. To bind to the value property of one object from the title object of another property, you must add a property to the object you are binding TO that looks like this:
valueBinding: "MyApp.anotherObject.title"
4 - Constants
A constant is a value that will not change throughout your application. Constant values can make your code both easier to read and help it to perform better. Instead of using the same string or number to represent some state, define constants on your application or classes instead.
Constants should always be named using all upper case, separating words with underscores. You should always define constants in your application namespace or on a class. Never define a global constant that is not prefixed by a namespace as it may conflict with other libraries you load.
MyApp.DEFAULT_CONTACT_COUNT = 23; // Good - defined on app namespace
MyApp.controller.HELP_LINK = "/help"; // Good - defined on a class
CONTACT_FIELDS = ['firstName', 'lastName']; // Bad - no globals!
5 - Other Coding Style Guidelines
SproutCore does not have a lot of specific coding style guidelines but the ones that it does have help a SproutCore application to be readable, maintainable, and easily extended.
5.1 - Two Space Soft tabs!
One very important, yet easy way to ensure that your code is readable is to have a consistent code indent scheme. SproutCore's standard is to have a two space soft tab instead of an actual tab. This makes the code much more readable and it is easy to set up your favorite text editor to do this.
5.2 - Value vs Content
Usually a property named value represents a simple JavaScript value of an object, such as a string, a number, etc. A property named content (or ending in Content) represents an Object that you will show one or more aspects of. For example, if you set the value property on an SC.LabelView to a string, the label view will show that string directly. If you set the content property on the SC.LabelView to a Contact object and then set the contentValueKey to fullName, then the SC.LabelView will show the value of the fullName property on the content object.
5.3 - Always Use Curly Brackets for If statements
It is OK to use the curly brackets after a while, for, or if statement but ONLY if the following bit does NOT fit on the same line. Never, ever, separate while, for, or if statements from their predicated onto separate lines without wrapping in curly braces. This creates lots of programming errors:
if (isReady) readyCount++; // OK - one line
if (isReady)
readyCount = oldReadCount + newReadyCount; // not OK!
if (isReady) {
readyCount = oldReadyCount + newReadyCount ;
} // OK - multi-line but wrapped in curly-Qs.
6 - Performance
While some style guidelines just make for more readable code, the suggestions in this section will actually make your code faster. Ignore them at your own peril.
6.1 - Always use ===
You should always use === and !== when comparing objects. This special form of equality is both faster and performs fewer transforms on the values you are comparing. It will behave more like you would expect compare to other languages than == or !=. If you want to see if a value is either null OR undefined, use SC.none(foo).
6.2 - Cache Length in For Loops
When writing for() loops, first capture the length you want to iterate through like so:
var idx;
for(idx = 0, len = items.length; idx < len; idx++) {
item = items[idx]; //do stuff...
}
Better yet, if the order you iterate does not matter, use a while loop like below since it is faster than using a for loop:
var idx = items.length;
while(--idx) {
//do stuff
}
6.3 - Avoid Creating Closures
Closures functions are a convenient way to define iterators and callbacks but they come at a price. When you define a closure function, the function will have to be recreated every time the surrounding function is called. In addition, closures can capture and hold your application's stack state for a long time, possibly leading to memory leaks, especially in IE.
Instead of using iterators like forEach() that require a closure, use simple for() or while() loops instead. If you do need to provide a function for a callback, define the function as a method on your object and pass a pointer to the method instead. All SproutCore classes that accept callback functions (such as addObserver(), removeObserver(), and invokeLater()) all accept both a target object and a method so you can avoid creating closures in most cases.
// Bad - this function creates a closure function
// to iterate over the array, AND creates a closure
// function to pass as a callback to addObserver().
//
// (This method also recreates the 'keys' array each
// time it is called)
setupObservers: function() {
var keys = ['firstName', 'lastName'];
keys.forEach(function(key) {
this.addObserver(key, function() {
console.log('%@ did change!'.fmt(key)) ;
});
});
}
// Good - this function uses a simple for loop, passes a
// target and method as the callback.
//
// (It also defines the keys array as a constant that is
// not recreated each time.)
OBSERVER_KEYS: ['firstName', 'lastName'],
keyDidChange: function(target, key) {
console.log('%@ did change!'.fmt(key));
},
setupObservers: function() {
var keys = this.OBSERVER_KEYS, len = keys.length, idx;
for(idx=0;idx<len;idx++) {
this.addObserver(keys[idx], this, this.keyDidChange);
}
}
6.4 - Beware of Redefining Arrays
Arrays are first class objects in JavaScript. This means every time you define an empty array, you are actually creating an object. When you write code, think about those times when you define new arrays and try to keep them to a minimum, especially in loops or other "hot" code. Instead of defining a new array, consider reusing an existing array and just resetting its length to 0.
// Good - reuses the array to collect temporary values
enqueItems: function() {
var items = this.get(items), len = items.length, idx;
var cur = [] ; // we'll reuse this one
for(idx=0;idx<len;idx++) {
var item = items[idx];
cur[0] = item.target ;
cur[1] = item.method;
this.enqueue(cur);
cur.length = 0; // reset array
}
}
Also, in these coding examples, you have have noticed that the {} are not on new lines, that is due to the author's stance and not an official guideline. That is up to the developer to choose how to format your curly-braces since after it is compressed, it won't really matter!
7 - Related Material
Below are links to some additional vidoes that discuss good Javascript programming practices.
8 - Changelog
- March 3, 2011: ported by Mike Ball from the original wiki entry written by Peter Bergstrom
- March 3, 2011: minor adjustments by Peter Wagenet
- August 13, 2013: converted to Markdown format for DocPad guides by Topher Fangio
- August 13, 2013: many gramatical fixes and minor formatting updates by Topher Fangio


Back to Lists
{{ words.name }}
{{ words.total }} words
Learned = {{ words.card_count }}
Flash Cards
Reset Count
Quiz = {{ words.quiz_count }}
Spelling Quiz
Reset Count
English
Chinese
{% for word in words.words %}
{{ word.english_name }}
{{ word.chinese_name }}
{% endfor %}


Updating and Validating Structural Finite Element Models for Dynamics Analysis (2008)
Model Correlation
Model Connection


A search module allows a user to query for results from a selection of data
A search can display a set of local results
A search can display a set of remote results
A search can display results using a template
The search component has full localization support. Read the localization docs for guidance.


public class ReportManager extends Object
| Modifier and Type | Method and Description |
|---|---|
static void |
attach(String attachmentType,
String attachmentName,
InputStream attachmentContent)
Adds a new attachment using the input parameters provided.
|
static void |
attach(String attachmentType,
String attachmentName,
String attachmentContent)
Adds a new attachment using the input parameters provided.
|
static void |
attachAsStep(String attachmentType,
String attachmentName,
InputStream attachmentContent)
Adds a new attachment using the input parameters provided.
|
static void |
attachAsStep(String attachmentType,
String attachmentName,
String attachmentContent)
Adds a new attachment using the input parameters provided.
|
static void |
attachFullLog()
|
static void |
attachTestLog()
Returns the log of the current test, and attaches it in the end
of the test
execution report.
|
static void |
generateAllureReportArchive()
|
static void |
getFullLog()
Deprecated.
|
static void |
getTestLog()
Deprecated.
attaching the log will be handled by the listeners package
instead. Returns the log of the current test, and attaches it in
the end of the test execution report.
|
static int |
getTotalNumberOfTests()
|
static boolean |
isDiscreetLogging()
|
static void |
log(Exception e)
Format an exception message and stack trace, and calls attach to
add it as a
log entry.
|
static void |
log(String logText)
Manages action counter and calls writeLog to format and print the
log entry.
|
static void |
logDiscreet(String logText)
|
static void |
logEngineVersion(Boolean isStartingExecution)
|
static void |
logTestInformation(String className,
String testMethodName,
String testDescription,
int testCaseNumber,
int totalTestCasesCount)
|
static void |
populateEnvironmentData()
|
static void |
setDiscreetLogging(boolean discreetLogging)
|
static void |
setTotalNumberOfTests(int totalNumberOfTests)
|
public static int getTotalNumberOfTests()
public static void setTotalNumberOfTests(int totalNumberOfTests)
public static void log(String logText)
logText
- the text that needs to be logged in this actionpublic static void logDiscreet(String logText)
public static void log(Exception e)
e
- the exception that will be logged in this action@Step(value="Attachment: {attachmentType} - {attachmentName}") public static void attachAsStep(String attachmentType, String attachmentName, InputStream attachmentContent)
attachmentType
- the type of this attachmentattachmentName
- the name of this attachmentattachmentContent
- the content of this attachment@Step(value="Attachment: {attachmentType} - {attachmentName}") public static void attachAsStep(String attachmentType, String attachmentName, String attachmentContent)
attachmentType
- the type of this attachmentattachmentName
- the name of this attachmentattachmentContent
- the content of this attachmentpublic static void attach(String attachmentType, String attachmentName, InputStream attachmentContent)
attachmentType
- the type of this attachmentattachmentName
- the name of this attachmentattachmentContent
- the content of this attachmentpublic static void attach(String attachmentType, String attachmentName, String attachmentContent)
attachmentType
- the type of this attachmentattachmentName
- the name of this attachmentattachmentContent
- the content of this attachment@Deprecated public static void getTestLog()
public static void attachTestLog()
@Deprecated public static void getFullLog()
public static void attachFullLog()
public static void generateAllureReportArchive()
public static void populateEnvironmentData()
public static void logEngineVersion(Boolean isStartingExecution)
public static void logTestInformation(String className, String testMethodName, String testDescription, int testCaseNumber, int totalTestCasesCount)
public static boolean isDiscreetLogging()
public static void setDiscreetLogging(boolean discreetLogging)
discreetLogging
- the discreetLogging to setCopyright © 2018. All rights reserved.