After you get your Shiny application to a state where it works, it’s often useful to have an automated system that checks that it continues to work as expected. There are many possible reasons for an application to stop working. These reasons include:
One way to detect these problems is with manual testing – in other words, by having a person interact with the app in a browser – but this can be time-intensive, inconsistent, and imprecise. Having automated tests can alert you to these kinds of problems quickly and with almost zero effort, after the tests have been created.
The shinytest package provides tools for creating and running automated tests on Shiny applications.
Shinytest uses snapshot-based testing strategy. The first time it runs a set of tests for an application, it performs some scripted interactions with the app and takes one or more snapshots of the application’s state. These snapshots are saved to disk so that future runs of the tests can compare their results to them.
To create tests, the easiest method is to use the recordTest()
function. This launches the application in a web browser and records your interactions with the application. These interactions are saved in a .R file, and are run using the strategy described above.
Shinytest is in active development:
library(devtools)
install_github("rstudio/webdriver")
install_github("rstudio/shinytest")
This is the general procedure for recording tests:
recordTest()
to launch the app in a test recorder.tests/
.tests/
directory.To record tests, run the following:
library(shinytest)
# Launch the target app (replace with the correct path)
recordTest("path/to/app")
In a separate R process, this launches the Shiny application to be tested. We’ll refer to this as the target app. This also launches a special Shiny application in the current R process which displays the target app in an iframe and has some controls outside the iframe. We’ll refer to this as the recorder app. You will see something like this:
On the left is the target app (in this case, the “Shiny Widgets Gallery”), and on the right is the recorder app (titled “Test event recorder”). Note that you may need to make the browser window wider because the recorder panel occupies some space.
The panel on the right displays some controls for the test recorder, as well as a list of Recorded events. As you interact with the target app – in other words, when you set inputs on the app – you will see those interactions recorded in the Recorded events list.
For testing a Shiny application, setting inputs is only one part. It’s also necessary to check that the application’s gives the correct outputs. This is accomplished by taking snapshots of the application’s state.
There are two ways to record output values. One way is to take a snapshot of the application’s state. This will record all input values, output values, and exported values (more on exported values later). To do this, click the “Take snapshot” button on the recorder app.
After modifying some inputs and taking a snapshot, it will look something like this:
It is also possible to take a target snapshot. This is a snapshot of on or more specified output (instead of the default, which is to snapshot the entire application). To do this, hold down the Control (or Command) button on your keyboard and click on an output; it will snapshot just that one output.
When you are done recording a sequence of events, click on the “Save script and exit test event recorder” button. If you are in the RStudio IDE, it will open the test script in the tests/
subdirectory of the application. In this case, the name of the script is mytest.R
:
app <- ShinyDriver$new("..")
app$snapshotInit("mytest")
app$snapshot()
app$setInputs(checkGroup = c("1", "2"))
app$setInputs(checkGroup = c("1", "2", "3"))
app$setInputs(action = "click")
app$snapshot()
When you quit the test recorder, it will automatically run the test script. There are three separate components involved in running the tests:
First is the test driver. This is the R process that coordinates the testing and controls the web browser. When working on creating tests interactively, this is the R process that you use.
Next is the Shiny process, also known as the server. This is the R process that runs the target Shiny application.
Finally, there is the web browser, also known as the client, which connects to the server. This is a headless web browser – one which renders the web page internally, but doesn’t display the content to the screen (PhantomJS).
When you exit the test recorder, it will by default automatically run the test script, and will print something like this:
Saved test code to /path/to/app/tests/mytest.R
Running mytest.R
====== Comparing mytest.R ======
No existing snapshots at mytest-expected/. This is a first run of tests.
Updating baseline snapshot at tests/mytest-expected
Renaming tests/mytest-current
=> tests/mytest-expected.
Behind the scenes, it runs testApp()
. You can manually run the tests with this:
testApp("myshinyapp", "mytest")
This will play back the interactions and record snapshots, as specified in the test script. The very first time the tests are run, they will be saved in a subdirectory of the app called tests/mytest-expected
. These are the expected results, and future test runs will be compared against them.
The directory will contain two files for each snapshot. For exmaple:
001.json
001.png
The .json file is a JSON representation of the state of the application when app$snapshot()
was called. The .png file is a screenshot of the application, which you can look at to inspect the state of the application.
The JSON file stores the state of all the input, output, and export values at the time of the snapshot:
{
"input": {
"action": 1,
"checkbox": true,
"checkGroup": ["1", "2", "3"],
"date": "2014-01-01",
"dates": ["2014-01-01", "2015-01-01"],
"file": null,
"num": 1,
"radio": "1",
"select": "1",
"slider1": 50,
"slider2": [25, 75],
"text": "Enter text..."
},
"output": {
"actionOut": "[1] 1\nattr(,\"class\")\n[1] \"integer\" \"shinyActionButtonValue\"",
"checkboxOut": "[1] TRUE",
"checkGroupOut": "[1] \"1\" \"2\" \"3\"",
"dateOut": "[1] \"2014-01-01\"",
"datesOut": "[1] \"2014-01-01\" \"2015-01-01\"",
"fileOut": "NULL",
"numOut": "[1] 1",
"radioOut": "[1] \"1\"",
"selectOut": "[1] \"1\"",
"slider1Out": "[1] 50",
"slider2Out": "[1] 25 75",
"textOut": "[1] \"Enter text...\""
},
"export": {}
}
If you are using a source control system (like git), you should check in the expected results.
After the initial test run, you can run the tests again in the future to check for changes in your application’s behavior. If there are no changes to the snapshots, you will just see something like this, with no additional output:
> testApp("path/to/app")
Running mytest.R
====== Comparing mytest ======
The results are saved to tests/mytest-current
, and compared against the saved results in tests/mytest-expected
. If the results are exactly the same, then the test is considered successful. It will return to the console with no additional output, and delete the tests/mytest-current
directory.
If there are any differences between the current and expected results, you’ll see output like this:
Running mytest.R
====== Comparing mytest ======
Differences detected between mytest-current/ and mytest-expected/:
Name Status
001.json != Files differ
001.png != Files differ
Would you like to view the differences between expected and current results [y/n]?
If you press y
and then Enter, it will open a Shiny application which shows the differences between the expected and current results. For screenshots, the differences will be highlighted in red. You can also choose different ways of viewing the differences in screenshots. It will look something like this:
After inspecting the changes, you can choose to update the expected results (that is, replace the old expected results with the new current results), or to just quit without updating.
You should update the results if the changes are expected. You should quit without updating if the changes are unexpected.
If you want to compare the results again in the future, without running testApp()
, you can run the following:
snapshotCompare("path/to/app/", "mytest")
In the example above, we had a single test script, named mytest.R
. If you want to have more than one set of tests for an application, you can record new tests, each with a different name. You can enter the name when recording your tests:
When you run testApp("path/to/app")
, it will run all the tests scripts in the application’s tests/
directory.
The test recorder is the easiest way to create test scripts, but it is not the only way. You can create and edit test scripts manually.
A test script has this basic structure: first, there is an initialization, then the tests, and finally the tests are wrapped up.
In the initialization, the script creates a new ShinyDriver object and tells it what name to use for this set of tests.
# Initialize a ShinyDriver object using the app in the test script's parent
# directory
app <- ShinyDriver$new("..")
app$snapshotInit("mytest")
Next, it defines some interactions with the application and takes snapshots.
app$setInputs(checkGroup = c("1", "2"))
app$setInputs(checkGroup = c("1", "2", "3"))
app$setInputs(action = "click")
app$snapshot()
app$setInputs(action = "click")
app$snapshot()
For customizing a script, the second portion – the interactions and snapshots – is the part you will want to modify. For snapshot-based testing, there are two methods that are used: app$setInputs()
and app$snapshot()
.
app$setInputs()
With app$setInputs()
, you provide the name of one or more inputs and corresponding values to set them to. Consider this set of directives:
app$setInputs(checkGroup = c("1", "2"))
app$setInputs(checkGroup = c("1", "2", "3"))
app$setInputs(action = "click")
Notice that we set the value of checkGroup
two times in a row. When we recorded this test script, it started with the value "1"
, and then we checked the "2"
and "3"
boxes. The recorded script set the value to c("1", "2")
, and then c("1", "2", "3")
. The c("1", "2")
value was simply an intermediate step.
It’s possible to simplify and speed up the tests by dropping the intermediate step, which leaves us with this:
app$setInputs(checkGroup = c("1", "2", "3"))
app$setInputs(action = "click")
And it’s also possible to set action
in the same call, resulting in this:
app$setInputs(
checkGroup = c("1", "2", "3"),
action = "click"
)
This will set the values of inputs simultaneously, which will make the tests run faster.
This is because, when app$setInputs()
is called, it normally returns control and moves on to the next step only after the server sends a response to the client.
The reason it waits for a response is so that a subsequent call to app$snapshot()
will be sure to capture the updated output values. If app$setInputs()
did not wait for a update, then, if the output update did not happen very quickly, a snapshot might capture the state of the application before the outputs are updated.
Because app$setInputs()
waits for an update each time, it is faster to set multiple inputs in a single call to app$setInputs()
than it is to have multiple calls to app$setInputs()
.
Note: In versions of Shiny before <IP_ADDRESS>00, calls to app$setInputs()
which did not result in an output value change would timeout, and print a message about setting a longer timeout or calling setInputs(wait_ = FALSE, values_ = FALSE)
. This is because those versions of Shiny did not send a response when no output values changed. As of Shiny <IP_ADDRESS>00, when in testing mode, Shiny always sends a response to input changes, even if no output values have changed, so this message should no longer appear.
app$snapshot()
There are two ways to use app$snapshot()
. The simplest way is to call it with no arguments:
app$snapshot()
The first time this is called in a test script, it will record all input, output, and exported values from the application, in a file called 001.json
. The next call will save the values in 002.json
, and so on.
Each time you call app$snapshot()
, it will also save a screen shot of the web browser, in a file 001.png
, 002.png
, and so on. These screen shots are useful for debugging your tests and inspecting what they’re doing. You can tell it to not take screen shots, to save space and make the tests run slightly faster, in the initialization step, with:
app$snapshotInit("mytest", screenshot = FALSE)
If you want to disable screenshots for a single snapshot, you can use:
app$snapshot(screenshot = FALSE)
If you want more targeted tests, you can snapshot specific items with the items
argument. For example, to capture the value of just the outputs named "a"
and "b"
, you would call:
app$snapshot(items = list(output = c("a", "b")))
The value passed to items
is a named list, where the output
is a character vector with the names of outputs to snapshot. You could also capture specific inputs or exports:
app$snapshot(items = list(
input = "n",
output = c("a", "b"),
export = c("e1", "e2")
))
Finally, if you want to snapshot all outputs but no inputs or exports, you can simply set output
to TRUE
:
app$snapshot(items = list(output = TRUE))
The same can be used to snapshot all inputs and/or all exports. To capture all outputs and exports, but no inputs:
app$snapshot(items = list(output = TRUE, export = TRUE))
If you need to debug a test script, you can run line-by-line from the R console. However, you likely will have modify the first line. It normally will refer to the Shiny application the parent directory (".."
):
app <- ShinyDriver$new("..")
When the test is run the usual way, with testApp()
, it will be run with the test directory as the working directory. However, when you run the tests from the command line, you generally will have a different working directory. To run the tests from a different directory, you will have to pass in the path to the application. It can be a relative path, for example:
app <- ShinyDriver$new("path/to/app")
The rest of the test script can be run unchanged.
As you step through the script, you can inspect the state of the application in a few different ways. One is to view a screenshot. You should not to call app$snapshot()
to get a screenshot, because it will increment the snapshot counter and shift the numbers of snapshots that really are part of the tests (e.g., snapshot 003 would become 004). Instead you can do this:
app$take_screenshot()
This will display the screenshot as if it were a plot. (In RStudio, it will show in the Viewer pane.) You can inspect the screenshot to see the state of the application.
It can also be useful to get the current input, output, and export values. As with screenshots, this is something that app$snapshot()
does, but we don’t want to call that function because increments the snapshot counter.
To fetch all values, you can call app$getAllValues()
. This returns a list, which you can inspect with the str()
function. It may look something like this:
vals <- app$getAllValues()
str(vals)
#> List of 3
#> $ input :List of 4
#> ..$ action :Classes 'integer', 'shinyActionButtonValue' int 0
#> ..$ checkbox : logi TRUE
#> ..$ checkGroup: chr "1"
#> ..$ text : chr "Enter text..."
#> $ output:List of 12
#> ..$ actionOut : chr "[1] 0\nattr(,\"class\")\n[1] \"integer\" #> \"shinyActionButtonValue\""
#> ..$ checkboxOut : chr "[1] TRUE"
#> ..$ checkGroupOut: chr "[1] \"1\""
#> ..$ textOut : chr "[1] \"Enter text...\""
#> $ export: Named list()
The same data is returned (invisibly) from each call to app$setInput()
, so you can also look at the return value from those function calls to get the same result.
The values retrieved this way can be used for expectation-based testing. For example, if you are using the testthat package for testing you could do something like:
vals <- app$getAllValues()
# Another option: save values when setting input values
# vals <- app$setInputs(checkbox = TRUE)
expect_identical(vals$output$checkboxOut, "[1] TRUE")
See the article about using shiny test with continuous integration.


public class Scanner
extends totalcross.lang.Object
Scanner access is only available when running on a native TotalCross VM; it
is not supported when running on Java. It is, though, emulated on Java:
a popup dialog will ask you for a barcode symbol which will be returned every time
the getData
method is called.
Since there is only one scanner per device, the scanner class is static. Activating the scanner causes the physical scanner to be powered, and enables the trigger. Deactivating the scanner removes the power from the scanner and prevents scans from taking place. The scanner should always be deactivated at the end of processing to prevent excessive battery drain.
When the scanner is activated, scan events will appear in the MainWindow's onEvent method. The scan events will contain a string describing either the item scanned or a battery error. Deactivating the scanner prevents scan events from being delivered.
Since barcodes can have many formats, this class includes a method to register the barcode types with the scanner. These types must each be individually set as parameters to the scanner. After all the parameter types have been set, the commitBarcodeParams method must be called to register the parameters with the scanner. Once this is done the scanner is able to decode the specified barcode types.
A typical processing sequence is given below:
if (!Scanner.activate() || !Scanner.setBarcodeParam(Intermec.AZTEC, true) || !Scanner.commitBarcodeParams()) return; ... if (!Scanner.deactivate()) return;Note: to generate an installation for the SYMBOL MC32, you must deploy using -WINCE (creates cab without compression), and not -WINMO (creates cab with compression).
| Modifier and Type | Field and Description |
|---|---|
static boolean |
isActive |
static Control |
listener
Set this listener to send all Scanner events to its onEvent method.
|
static String |
scanManagerVersion
The scanner version.
|
| Constructor and Description |
|---|
Scanner() |
| Modifier and Type | Method and Description |
|---|---|
protected static void |
_onEvent(int type)
Dispatch the event to the current listener (associated through the
listener public member. |
static boolean |
activate()
Activate the scanner.
|
static boolean |
commitBarcodeParams()
Commit the barcode parameters to the scanner.
|
static boolean |
deactivate()
Deactivate the scanner.
|
static String |
getData()
Get the decoded string of what has been scanned.
|
static String |
getScanManagerVersion()
Get the scan manager version as an hexadecimal String.
|
static String |
getScanPortDriverVersion()
Get the Scanner Port Driver version as an hexadecimal string.
|
static void |
proprietaryScanLoad(Runnable scanLoad) |
static String |
readBarcode(String mode)
Reads a barcode using ZXing for Android.
|
static boolean |
setBarcodeLength(int barcodeType,
int lengthType,
int min,
int max)
Set the length of a barcode.
|
static boolean |
setBarcodeParam(int barcodeType,
boolean enable)
Set a scanner parameter defining whether a barcode format will be used
in scanning.
|
static boolean |
setParam(int type,
int barcodeType,
int value)
Set a parameter for the barcode.
|
static void |
setParam(String what,
String value)
Used in the Honeywell Android barcode scanners.
|
public static boolean isActive
public static String scanManagerVersion
public static Control listener
public static void proprietaryScanLoad(Runnable scanLoad)
public static boolean activate()
Note: On Android Intermec, you can't activate the scanner if it is off in the settings. Moreover, you should not set the scanner and virtual wedge settings off and then try to use the scanner. Even though your app won't crash or hang, the device might not behave properly. There is no way to check if the device settings are off in the settings or in the app.
public static boolean setBarcodeParam(int barcodeType, boolean enable)
barcodeType
- the type of barcode under considerationenable
- a flag to enable or disable decoding barcodes of this type.
Note: On Android Intermec, you CAN'T set enable a barcode type the scanner is not activate. In this case, this method will return false.
public static boolean setParam(int type, int barcodeType, int value)
With Datalogic scanners, the SECOND parameter is not used (always pass 0 to it); and don't forget to call the commitBarcodeParams method.
Values valid for SYMBOL scanners:
// triggering modes #define LEVEL 0x00 #define PULSE 0x02 #define HOST 0x08 // Linear code type security #define SECURITY_LEVEL0 0x00 #define SECURITY_LEVEL1 0x01 #define SECURITY_LEVEL2 0x02 #define SECURITY_LEVEL3 0x03 #define SECURITY_LEVEL4 0x04 // UPC/EAN Supplementals #define IGNORE_SUPPLEMENTALS 0x00 #define DECODE_SUPPLEMENTALS 0x01 #define AUTODISCRIMINATE_SUPPLEMENTALS 0x02 // Transmit Check Digit options #define DO_NOT_TRANSMIT_CHECK_DIGIT 0x00 #define TRANSMIT_CHECK_DIGIT 0x01 // Preamble options #define NO_PREAMBLE 0x00 #define SYSTEM_CHARACTER 0x01 #define SYSTEM_CHARACTER_COUNTRY_CODE 0x02 // CheckDigit verification options #define DISABLE_CHECK_DIGIT 0x00 #define USS_CHECK_DIGIT 0x01 #define OPCC_CHECK_DIGIT 0x02 // MSI Plessey checkdigit options #define ONE_CHECK_DIGIT 0x00 #define TWO_CHECK_DIGITS 0x01 // MSI Plessey check digit algorithms #define MOD10_MOD11 0x00 #define MOD10_MOD10 0x01 // Transmit Code ID Character options #define AIM_CODE_ID_CHARACTER 0x01 #define SYMBOL_CODE_ID_CHARACTER 0x02 // Scan data transmission formats #define DATA_AS_IS 0x00 #define DATA_SUFFIX1 0x01 #define DATA_SUFFIX2 0x02 #define DATA_SUFFIX1_SUFFIX2 0x03 #define PREFIX_DATA 0x04 #define PREFIX_DATA_SUFFIX1 0x05 #define PREFIX_DATA_SUFFIX2 0x06 #define PREFIX_DATA_SUFFIX1_SUFFIX2 0x07 // Scan angle options #define SCAN_ANGLE_WIDE 0xB6 #define SCAN_ANGLE_NARROW 0xB5
This method is ignored for Intermec scanners.
public static boolean commitBarcodeParams()
Not used on the Windows CE and Android platforms.
public static boolean setBarcodeLength(int barcodeType, int lengthType, int min, int max)
This method is ignored for Intermec scanners. The lengthType must be one of the following values:
barcodeType
- One of the BARxxxx constantslengthType
- 0 (variables length, min, and max are ignored), 1 (length = min), 2 (length = min || length = max), 3 (min <= length <= max). Careful: in Motorola Scanners, min and max must be used in inverted order due to a bug in the MOTOROLA API.min
- The minimum valuemax
- The maximum valuepublic static String getData()
Note: On Android Intermec, you should first set some parameters before fetching data or else it might crash after 10 or 15 reads.
public static String getScanManagerVersion()
public static String getScanPortDriverVersion()
public static boolean deactivate()
protected static void _onEvent(int type)
listener
public member. Called from the native library.
If there are no assigned listeners, the event is sent to the top most window,
and the window is validated.public static String readBarcode(String mode)
public static void setParam(String what, String value)
Scanner.setParam(Honeywell.START_BATCH,"true"); ... set other parameters Scanner.setParam(Honeywell.END_BATCH,"true");Dont forget the start and end batch, otherwise it won't work! For boolean parameters, use "true" or "false". For integer parameters, use the integer passed as String.


Stats
Latest Orders
| #12345 - Joe Bloggs Paid | $112.00 |
| #12345 - Joe Bloggs Dispatched | $112.00 |
| #12345 - Joe Bloggs Refunded | $112.00 |
| #12345 - Joe Bloggs Awaiting Payment | $112.00 |
| #12345 - Joe Bloggs Failed | $112.00 |
| #12345 - Joe Bloggs Cancelled | $112.00 |
| #12345 - Joe Bloggs Paid | $112.00 |
| View more orders |
| News article title | Today at 12:01 |
| Another news article title | Yesterday at 16:34 |
| A third news article title | 22nd June 2014 |
| This news article title spans onto two lines so we can see what it will look like | 21st June 2014 |
| A final news article title | 20th June 2014 |
| Read more news |
Enquiries
| Customer enquiry New | Today at 12:01 |
| Another customer enquiry New | Yesterday at 16:34 |
| A third customer enquiry | 22nd June 2014 |
| This customer enquiry spans onto two lines so we can see what it will look like | 21st June 2014 |
| A final customer enquiry | 20th June 2014 |
| View more enquiries |


instatrack
Track Instagram tags in real time.
Sign in with Instagram
Created by
Qasim Iqbal
Fork it on
GitHub


{% extends 'accounts/main.html' %} {% block content %}
Your password has been set. You may go ahead and log in now.


--- layout: posts title: Array based stack date: 2012-11-07 tags: c, data structures category: code permalink: /code/array-based-stack/index.html excerpt_separator: ---
This article discusses the implementation of an array based stack as coded in c++.
The following code is the unit tests developed for the array based stack. See Quick Unit Testing in c++ for an article on how the unit test code was developed.
The following code was developed to meet the unit tests described in StackUnitTests.
The following is a list of methods within the Stack class and their respective complexity.
Please leave some thoughts below and thanks for the read.


18th July 2020
JavaScript is the very engaging and adventurous friend of CSS and HTML:
To help me understand the different roles of
HTML and CSS I like to think of them in terms of a structure - such a house or an organism. Following this thought pattern, HTML would be considered the ‘bones’
or frame of a structure. In tech, it is considered to be the raw content and the information that is wishing to be communicated. In comparison, CSS would be the
flesh on the bones or the paint on the walls. There are lots of variations in what people or buildings look like, we can consider these differences in style or
appearance. In tech, CSS brings color and unique aesthetic properties to the information we want to communicate in order to make it more attractive and somewhat
more palatable.
Control Flow
Control flow is the sequence in which statements in a script are executed:
Like when you recreate that dish from masterchef, you will follow the steps in a recipe in an order to eventually achieve the desired outcome.
However, JavaScript is celebrated as being dynamic and responsive (a lot more so than a standard issue recipe), and so uses different operators (for example - operators
that use mathematical arithmetic) to respond differently according to changing information that is supplied to it. Using comparison and logical operators, we can define
terms which enable JavaScript to discern true or false statements and alter its action according to each outcome. These operators can be used simply or with more complexity,
essentially providing 1 or more alternatives depending on an outcome. Like having a plan contingency plan in place so it can execute a response for every possible outcome
e.g plan a), b), c) and so on.
Loops
Loops are a feature that affects the order of code execution and will repeatedly evaluates or runs a block of code until a
specified condition is met or time frame is complete:
Each ‘run through’ is known as an iteration.
‘For loops’ - will iterate until a specified condition returns false
‘Do while’ - loops do the same except they will always iterate at least once before checking the specified condition is true or false.
‘While loops’ - are similar to ‘for loops’ and will only run as long as the specified condition equates to true. In contrast to ‘for loops’, while loops the term that defines its iteration can be written anywhere in the body of the loop - not just at the top.
Bellow I have illustrated what the struture of a 'for loop'..:
A loop in action is similar to me showering. I will lather myself beginning from my head and down to my toes with soap with soap until I am covered and then rinse with
water repeatedly until I can no longer feel or see soap on my body.
And input my own example in the 'for' statement:
DOM stands for Document Object model and is considered The glue between HTML, CSS and JavaScript :
It is an object-oriented representation of a web page, which can be modified with a scripting language such as JavaScript i.e a pages content is stored in the DOM and may
be accessed and manipulated (have structure, style and content changed) via JavaScript.
In other words, the DOM is a programming interface for HTML and XML documents, and is a hierarchical presentation that browsers use to comprehend a document and object
within it on the web
Any changes made to the DOM via JavaScript is reflected in what gets shown in the browser, therefore you can dynamically add elements, remove them, move them around, modify attributes on them, set inline CSS styles, and perform all sorts of other types of things. Isn’t that INCREDIBLE!
Different browsers have different implementations of the DOM,
But every web browser uses some document object model to make web pages accessible via JavaScript.
Because working with the DOM you can allow you to manipulate and view so much of what creates the webpage, i.e get a reference to an element in the DOM, change its text content, apply new styles to it, create new elements and add them to the current element as children, or even delete it altogether, it becomes a
great tool to explore alterations to a site in real time, seeing immediately the impact of these changes on a web page.
Arrays and objects are both ways of collecting and storing data in JavaScript.
Objects:
Objects are a particular data type that can store a collection of properties or characteristics in the form of a key and a value. For example, an object could contain many different properties that pertain to a single person:
var client = { Name (key): ‘Emma’ (value), Age (key): 28 (value), Eye color (key): ‘Brown’ (value) etc... };
Accessing/ adding/ changing and removing properties from an object is achieved using either dot or bracket notation. For example to get the value of the Age key in the above
example I could use:
a) client.age
Or
b) client[‘age’]
And we can change the age value:
client.age = 82; (Yup, I’m feeling it today!)
You can use ‘for...in loops’ to iterate through properties in an object: or by adding the ‘forEach()’ method to Object.keys():
Arrays:
Arrays are a particular type of variable that can store a collection of values for that one variable. For example, an array could contain
many different values (or names in this example) that pertain to a single person’s 6 cats. Cats in this example are the variable and the 6 different names
are the 6 different values for that one variable:
var emmasCats = [‘Bree’, ‘Sam’, ‘Bevuss, ‘Lyall’, ‘Lavender’, ‘Paprika’]
To access/ add/ change and remove items from an array we need to use zero-based indexing which means that the first value in the list of values is always 0, then 1,2,3 etc. If I want to access ‘Lavender’ I would write:
emmasCats[4];
Items can be added and removed from the beginning or end of an array using the push(), pop(), unshift(), and shift() methods:
push() - Adds item(s) to the end of an array
emmasCats.push(‘Poppy’);
pop() - Removes the last item from an array
emmasCats.pop();
unshift() - Adds item(s) to the beginning of an array
emmasCats.unshift('Celia', 'Charlie');
shift() - Removes the first item from an array
emmasCats.shift();
You can loop through items in an array in a few ways.
There’s the standard for loop: There’s also the ‘for…of’ loop: Or we can utilize the ‘forEach()’ method:
A JavaScript function is a container of code that performs an assigned task when it is called to do so.
The structure of a function is:
function name(parameter1, parameter2, parameter3) {
// code to be executed
}
For example:
And when ‘called’ with real values:
Functions are super cool because they can be reused - how eco friendly! We only need to describe what a function does, and then we can assign an infinite combination of different values (aka arguments) and get different results throughout a project.
Emma x


Module: ActiveSupport::Testing::Assertions
| Relationships & Source Files | |
| Extension / Inclusion / Inheritance Descendants | |
|
Included In:
::ActionCable::Channel::TestCase ,
::ActionCable::Connection::TestCase ,
::ActionCable::TestCase ,
::ActionController::TestCase ,
::ActionDispatch::IntegrationTest ,
::ActionDispatch::SystemTestCase ,
::ActionMailbox::TestCase ,
::ActionMailer::TestCase ,
::ActionMailer::TestCase::Behavior ,
::ActionMailer::TestHelper ,
::ActionView::TestCase ,
::ActiveJob::TestCase ,
::ActiveJob::TestHelper ,
::ActiveSupport::TestCase ,
::Rails::Generators::TestCase
| |
| Defined in: | activesupport/lib/active_support/testing/assertions.rb |
Constant Summary
-
UNTRACKED =
Internal use only
# File 'activesupport/lib/active_support/testing/assertions.rb', line 8Object.new
Instance Method Summary
-
#assert_changes(expression, message = nil, from: UNTRACKED, to: UNTRACKED, &block)
Assertion that the result of evaluating an expression is changed before and after invoking the passed in block.
-
#assert_difference(expression, *args, &block)
Test numeric difference between the return value of an expression as a result of what is evaluated in the yielded block.
-
#assert_no_changes(expression, message = nil, from: UNTRACKED, &block)
Assertion that the result of evaluating an expression is not changed before and after invoking the passed in block.
-
#assert_no_difference(expression, message = nil, &block)
Assertion that the numeric result of evaluating an expression is not changed before and after invoking the passed in block.
-
#assert_not(object, message = nil)
Asserts that an expression is not truthy.
-
#assert_nothing_raised
Assertion that the block should not raise an exception.
-
#assert_raise(*exp, match: nil, &block)
Alias for #assert_raises.
-
#assert_raises(*exp, match: nil, &block)
(also: #assert_raise)
Asserts that a block raises one of
exp
. - #_assert_nothing_raised_or_warn(assertion, &block) private
Instance Method Details
#_assert_nothing_raised_or_warn(assertion, &block) (private)
[ GitHub ]# File 'activesupport/lib/active_support/testing/assertions.rb', line 265
def _assert_nothing_raised_or_warn(assertion, &block) assert_nothing_raised(&block) rescue Minitest::UnexpectedError => e if tagged_logger && tagged_logger.warn? warning = <<~MSG #{self.class} - #{name}: #{e.error.class} raised. If you expected this exception, use `assert_raises` as near to the code that raises as possible. Other block based assertions (e.g. `#{assertion}`) can be used, as long as `assert_raises` is inside their block. MSG tagged_logger.warn warning end raise end
#assert_changes(expression, message = nil, from: UNTRACKED, to: UNTRACKED, &block)
Assertion that the result of evaluating an expression is changed before and after invoking the passed in block.
assert_changes 'Status.all_good?' do
post :create, params: { status: { ok: false } }
end
You can pass the block as a string to be evaluated in the context of the block. A lambda can be passed for the block as well.
assert_changes -> { Status.all_good? } do
post :create, params: { status: { ok: false } }
end
The assertion is useful to test side effects. The passed block can be anything that can be converted to string with #to_s
.
assert_changes :@object do
@object = 42
end
The keyword arguments :from
and :to
can be given to specify the expected initial value and the expected value after the block was executed.
assert_changes :@object, from: nil, to: :foo do
@object = :foo
end
An error message can be specified.
assert_changes -> { Status.all_good? }, 'Expected the status to be bad' do
post :create, params: { status: { incident: true } }
end
# File 'activesupport/lib/active_support/testing/assertions.rb', line 191
def assert_changes(expression, = nil, from: UNTRACKED, to: UNTRACKED, &block) exp = expression.respond_to?(:call) ? expression : -> { eval(expression.to_s, block.binding) } before = exp.call retval = _assert_nothing_raised_or_warn("assert_changes", &block) unless from == UNTRACKED error = "Expected change from #{from.inspect}, got #{before}" error = "#{}.\n#{error}" if assert from === before, error end after = exp.call error = "#{expression.inspect} didn't change" error = "#{error}. It was already #{to}" if before == to error = "#{}.\n#{error}" if refute_equal before, after, error unless to == UNTRACKED error = "Expected change to #{to}, got #{after}\n" error = "#{}.\n#{error}" if assert to === after, error end retval end
#assert_difference(expression, *args, &block)
Test numeric difference between the return value of an expression as a result of what is evaluated in the yielded block.
assert_difference 'Article.count' do
post :create, params: { article: {...} }
end
An arbitrary expression is passed in and evaluated.
assert_difference 'Article.last.comments(:reload).size' do
post :create, params: { comment: {...} }
end
An arbitrary positive or negative difference can be specified. The default is 1
.
assert_difference 'Article.count', -1 do
post :delete, params: { id: ... }
end
An array of expressions can also be passed in and evaluated.
assert_difference [ 'Article.count', 'Post.count' ], 2 do
post :create, params: { article: {...} }
end
A hash of expressions/numeric differences can also be passed in and evaluated.
assert_difference ->{ Article.count } => 1, ->{ Notification.count } => 2 do
post :create, params: { article: {...} }
end
A lambda or a list of lambdas can be passed in and evaluated:
assert_difference ->{ Article.count }, 2 do
post :create, params: { article: {...} }
end
assert_difference [->{ Article.count }, ->{ Post.count }], 2 do
post :create, params: { article: {...} }
end
An error message can be specified.
assert_difference 'Article.count', -1, 'An Article should be destroyed' do
post :delete, params: { id: ... }
end
# File 'activesupport/lib/active_support/testing/assertions.rb', line 101
def assert_difference(expression, *args, &block) expressions = if expression.is_a?(Hash) = args[0] expression else difference = args[0] || 1 = args[1] Array(expression).index_with(difference) end exps = expressions.keys.map { |e| e.respond_to?(:call) ? e : lambda { eval(e, block.binding) } } before = exps.map(&:call) retval = _assert_nothing_raised_or_warn("assert_difference", &block) expressions.zip(exps, before) do |(code, diff), exp, before_value| actual = exp.call error = "#{code.inspect} didn't change by #{diff}, but by #{actual - before_value}" error = "#{}.\n#{error}" if assert_equal(before_value + diff, actual, error) end retval end
#assert_no_changes(expression, message = nil, from: UNTRACKED, &block)
Assertion that the result of evaluating an expression is not changed before and after invoking the passed in block.
assert_no_changes 'Status.all_good?' do
post :create, params: { status: { ok: true } }
end
Provide the optional keyword argument :from
to specify the expected initial value.
assert_no_changes -> { Status.all_good? }, from: true do
post :create, params: { status: { ok: true } }
end
An error message can be specified.
assert_no_changes -> { Status.all_good? }, 'Expected the status to be good' do
post :create, params: { status: { ok: false } }
end
# File 'activesupport/lib/active_support/testing/assertions.rb', line 238
def assert_no_changes(expression, = nil, from: UNTRACKED, &block) exp = expression.respond_to?(:call) ? expression : -> { eval(expression.to_s, block.binding) } before = exp.call retval = _assert_nothing_raised_or_warn("assert_no_changes", &block) unless from == UNTRACKED error = "Expected initial value of #{from.inspect}" error = "#{}.\n#{error}" if assert from === before, error end after = exp.call error = "#{expression.inspect} changed" error = "#{}.\n#{error}" if if before.nil? assert_nil after, error else assert_equal before, after, error end retval end
#assert_no_difference(expression, message = nil, &block)
Assertion that the numeric result of evaluating an expression is not changed before and after invoking the passed in block.
assert_no_difference 'Article.count' do
post :create, params: { article: invalid_attributes }
end
A lambda can be passed in and evaluated.
assert_no_difference -> { Article.count } do
post :create, params: { article: invalid_attributes }
end
An error message can be specified.
assert_no_difference 'Article.count', 'An Article should not be created' do
post :create, params: { article: invalid_attributes }
end
An array of expressions can also be passed in and evaluated.
assert_no_difference [ 'Article.count', -> { Post.count } ] do
post :create, params: { article: invalid_attributes }
end
# File 'activesupport/lib/active_support/testing/assertions.rb', line 153
def assert_no_difference(expression, = nil, &block) assert_difference expression, 0, , &block end
#assert_not(object, message = nil)
Asserts that an expression is not truthy. Passes if object
is nil
or false
. “Truthy” means “considered true in a conditional” like if foo
.
assert_not nil # => true
assert_not false # => true
assert_not 'foo' # => Expected "foo" to be nil or false
An error message can be specified.
assert_not foo, 'foo should be false'
# File 'activesupport/lib/active_support/testing/assertions.rb', line 21
def assert_not(object, = nil) ||= "Expected #{mu_pp(object)} to be nil or false" assert !object, end
#assert_nothing_raised
Assertion that the block should not raise an exception.
Passes if evaluated code in the yielded block raises no exception.
assert_nothing_raised do
perform_service(param: 'no_exception')
end
# File 'activesupport/lib/active_support/testing/assertions.rb', line 48
def assert_nothing_raised yield.tap { assert(true) } rescue => error raise Minitest::UnexpectedError.new(error) end
#assert_raise(*exp, match: nil, &block)
Alias for #assert_raises.
# File 'activesupport/lib/active_support/testing/assertions.rb', line 39
alias :assert_raise :assert_raises
#assert_raises(*exp, match: nil, &block) Also known as: #assert_raise
Asserts that a block raises one of exp
. This is an enhancement of the standard ::Minitest
assertion method with the ability to test error messages.
assert_raises(ArgumentError, match: /incorrect param/i) do
perform_service(param: 'exception')
end
# File 'activesupport/lib/active_support/testing/assertions.rb', line 34
def assert_raises(*exp, match: nil, &block) error = super(*exp, &block) assert_match(match, error. ) if match error end


Python for .NETPython for .NET is a package that gives Python programmers nearly seamless integration with the .NET Common Language Runtime (CLR) and provides a powerful application scripting tool for .NET developers. Using this package you can script .NET applications or build entire applications in Python, using .NET services and components written in any language that targets the CLR (Managed C++, C#, VB, JScript). Note that this package does not implement Python as a first-class CLR language - it does not produce managed code (IL) from Python code. Rather, it is an integration of the C Python engine with the .NET runtime. This approach allows you to use use CLR services and continue to use existing Python code and C-based extensions while maintaining native execution speeds for Python code. If you are interested in a pure managed-code implementation of the Python language, you should check out the IronPython project, which is in active development. Python for .NET is currently compatible with Python releases 2.5 and greater. To subscribe to the Python for .NET mailing list or read the online archives of the list, see the mailing list information page. You can also send questions or comments to me at<EMAIL_ADDRESS>or use the Python for .NET issue tracker to report issues. My blog site is also (sometimes) a good source for more information on Python for .NET ;)
|


§273-14 Penalty for violating. Any person violating any bylaw or regulation approved in section 273-13, shall be fined not more than $25 and costs; and in default of payment, shall be imprisoned not more than three months. [L 1878, c 29, §25; RL 1925, §901; RL 1935, §1807; RL 1945, §5065; RL 1955, §106-14; HRS §273-14]
Cross References
Classification of offense and authorized punishment, see §§701-107, 706-640, 663.


| DOSE: |
3 hits |
oral |
MDMA |
(pill / tablet) |
| |
2 drops |
oral |
LSD |
(liquid) |
It took me 6 months to “discover” the acid since the first time I took it. The first times were all meaningless compared to what happened that strange night. The setting for the trip began about a week before it happened. I had a break from work and decided to visit Amsterdam. I was traveling by myself and since the moment I got there I kept counting the days backward to April 30th (queensday). The day that I would take the acid at the party. Unfortunately, a week wasn’t enough time for me to find some good acid, and I got to the party empty handed. I was unhappy with that situation. I waited a long time for this day and was sure that by now I would have had the acid already. Like I said, my first blotters were all weak and I was sure that in Amsterdam the day would come. I was in a bad mood and didn’t feel like asking people at the party if they got some. Instead, I swallowed 3 extacys and was hoping for the best. A few hours later, it happened.
It seemed like things were just fine. I had a great time at the party and the whole acid story didn’t bother me. I kept thinking about all the good times I had during my week in Amsterdam and all the people seemed nice and friendly. Suddenly, things began to slow down. Slower and slower till my vision came to a complete stand still. I heard a blast inside my head and for a short time I couldn’t see a thing. When my vision came back it was still frozen, but a lot worse: it looked as if it was being shaken.
That was a strange sight. I remember thinking that if my mind is like a peaceful puddle, someone just threw a rock in there and completely blurred it. After a minute or so things were going back to normal.  I couldn’t figure it out.  He raised his arms to the air while shouting: “I can’t believe it! It was me! What a classic!” Clearly this guy was on way too much drugs. Normally this wouldn’t bother me, but it did. I kept staring at him. I had a feeling that he was some how related to my loss of vision experience. Bits of information came back to me one after another, building back my memory. Now I remember. Now I know what happened. And it’s pretty bad.
Earlier that night I was in a pretty bad shape cause of the pills. I did some things that I wouldn’t normally do, but I couldn’t help it, and only after they happened I remembered doing them. It was like having a delay between the reality and my mind, and this was one of those things:
The crazy guy and his friend were giving away MDMA and LSD for the people at the party (back then he wasn’t crazy). He came to me and asked me gently: “Excuse me, would you like, some, L S D?” I said yes and took a sip from his bottle.
When it came to me that this is what happened I was scared to death. I took too much. And not only that, the guy who gave me the LSD was flipping out, and I’m probably next… I decided that the best thing to do was to walk away. I turned my head and then I found my self in a new place.
It was dark. I couldn’t see or hear a thing. Every once in a while I saw a star shining from a distance, and then disappear. I didn’t move, and it felt like I’ve been there for hours. I saw a person in front of me. I tried to look at him but I couldn’t focus. He was moving, and when I tried to understand what he was doing he was actually standing still. So I tried to look at him and he was moving again… I understood that it was completely useless and gave up on him.
“What is this place?” I asked myself.
“That, my friend, is LSD” the person answered.
I couldn’t understand the meaning of the word. It didn’t sound familiar.
“LSD? What is LSD?”
I just couldn’t understand. Was it a name of a place? Was it a feeling? Is LSD alive? I didn’t know where to start looking for the answer. The word was completely meaningless. I knew that the whole situation was wrong, that I had to get out of there, but I didn’t know how. Every time that word came up all I saw was something that resembles a trail of a comet.
“What is it?!” I asked again, desperately. And then the blurred person answered: “It’s all the things combined. A trip.”
Less then a second after it happened I found my self back at the party. I could remember everything that just happened and was in complete shock. I just had a classic trip! I was walking in space and talking to god. It was simply unbelievable. I wasn’t afraid anymore, I was happy. So happy that I completely forgot about my condition. At that point I decided that I want to take home with me some blotters so I can repeat that experience. I found the guy with the acid and asked him if he has some. He said yes. While I was busy trying to take some money out of my pocket, I failed to see that he misunderstood me. He took out a small bottle and laid a drop on my right hand. I froze.
“You don’t have any paper?” I asked.
“No. That’s all I got left and I’m just spreading it around”.
That wasn’t what I needed. I had enough chemicals running around in me without taking a second dose of acid, but I took it anyway. It was bitter.  I came back to the party and analyzed my position:
It seems that somehow I got into something that was way over my league, but I was able to escape from it. I found my way back to the real world and what’s the first thing I do? I choose to take another drop!
That’s bad. The first one didn’t even wear off. When the second one will hit me, it’s gonna get ugly. I know it.
Nothing more to do then wait and try to prepare myself for what is about to happen.
It wasn’t long before my vision started slowing down again. This time I knew what would happen but I couldn’t stop it. I heard another blast inside my head and once again things froze in place. I felt electricity all over my body and in my head. When I woke up I couldn’t remember a thing. I didn’t know my name, where I was or what I was doing there. I had just a bit of common sense left, and I said to myself that if there is one thing that is need to be done, it is to prove to myself that I am not crazy and say my name. No name. No nothing. I didn’t know anything.
“Listen to me”, I said (to myself).  Probably for good”.
“Wait, don’t panic” I answered. “Just give me a few seconds to add things up and I’ll show you that I’m not crazy”.
I took a deep breath and looked around. I could see that I am in a party, and I could remember my name. I was quite relieved that once again I found my way back to reality, but I wasn’t aware that since that moment, I was living in a distorted reality. I convinced myself that my home was in Amsterdam, and that the people at the party are my friends. None of the above was true, but there was no way that I could have figured it out. It was like a dream. I could feel that things around me were weird in a certain way, but I was not aware of the fact that I was dreaming (or tripping) and I just accepted all the weird stuff that happened.
I was enjoying my private world, with my private reality that I made up. I had no worries because there was nothing to worry about. Nothing was wrong. All the problems seemed to have gone away and instead I got waves of positive energy. I talked to people as if I knew them for ages. I actually remembered things that never happened, but I believed they did. It could have lasted forever, but at a certain point I had to go out and vomit. After I went it was clear that it was time to go home. I started looking for my car, and couldn’t find it. I was afraid that it was stolen. I didn’t know what to do. How am I going to get home?
And then it hit me.
There is no car. There are no friends who will take care of me. I am all alone in a foreign country.
This isn’t my home.
It was like everything that happened so far was compressed into one second of harsh reality.
I suddenly realized what was happening the entire evening, all at once.
This was just too much. I was now aware of the fact that I can’t tell the difference between what is real and what is not. It was like waking up from a dream only I wasn’t sleeping. How could it happen? I spent some time out at the fresh air, without psychedelic music thumping in my head. I felt like the trip was crawling out of me and was going back to where it came from. Its funny, I spent 6 months of my life trying to reveal what is behind the LSD, and the moment I gave up on it I got caught off guard, twice… I guess that no matter how hard you can look for it, eventually it will find you.
Looking back at that night I can see why the trip was developing the way it did. When you put something in the oven you know that when it will come out, it will taste like its ingredients. Eating acid is a way of finding out what your ingredients are. What you experience in a trip is for you alone. It cannot be shared. There are a few things that can be shared, like what you have just read. But keep in mind that it is only the tip of the iceberg and that it goes a lot deeper then a couple of written pages. The main thing I learned is that acid is something I have to deal with after taking it, rather then during.
That’s when I have to give explanations about things that just cannot be explained.
Experience Reports are the writings and opinions of the individual authors who submit them.
Some of the activities described are dangerous and/or illegal and none are recommended by Erowid.


Comparison with action calculi
This style of semantics is most similar to Milner's action
calculi, except that in this presentation control edges are
used to control order of evaluation, where in Milner's presentation,
evaluation is delayed by placing sub-graphs inside controls,
for example (using slightly different notation):
There is a trade-off here between categorical simplicity
(monoidal categories v. premonoidal pre-2-cagegories)
and graphical simplicity
(control edges v. controls containing sub-graphs).


There are many lives that depend on yours. You can make a change. Together we can help educate them via technology


1.Collapsible
Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. 3 wolf moon officia aute, non cupidatat skateboard dolor brunch. Food truck quinoa nesciunt laborum eiusmod. Brunch 3 wolf moon tempor, sunt aliqua put a bird on it squid single-origin coffee nulla assumenda shoreditch et. Nihil anim keffiyeh helvetica, craft beer labore wes anderson cred nesciunt sapiente ea proident. Ad vegan excepteur butcher vice lomo. Leggings occaecat craft beer farm-to-table, raw denim aesthetic synth nesciunt you probably haven't heard of them accusamus labore sustainable VHS.
Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. 3 wolf moon officia aute, non cupidatat skateboard dolor brunch. Food truck quinoa nesciunt laborum eiusmod. Brunch 3 wolf moon tempor, sunt aliqua put a bird on it squid single-origin coffee nulla assumenda shoreditch et. Nihil anim keffiyeh helvetica, craft beer labore wes anderson cred nesciunt sapiente ea proident. Ad vegan excepteur butcher vice lomo. Leggings occaecat craft beer farm-to-table, raw denim aesthetic synth nesciunt you probably haven't heard of them accusamus labore sustainable VHS.
Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. 3 wolf moon officia aute, non cupidatat skateboard dolor brunch. Food truck quinoa nesciunt laborum eiusmod. Brunch 3 wolf moon tempor, sunt aliqua put a bird on it squid single-origin coffee nulla assumenda shoreditch et. Nihil anim keffiyeh helvetica, craft beer labore wes anderson cred nesciunt sapiente ea proident. Ad vegan excepteur butcher vice lomo. Leggings occaecat craft beer farm-to-table, raw denim aesthetic synth nesciunt you probably haven't heard of them accusamus labore sustainable VHS.
2.Card
Card title
Some quick example text to build on the card title and make up the bulk of the card's content.
Go somewhereCard title
Some quick example text to build on the card title and make up the bulk of the card's content.
Go somewhereCard title
Some quick example text to build on the card title and make up the bulk of the card's content.
Go somewhere


{% extends "tutorial.html" %} {% load mixin from templatefilters %} {% block pagebreadcrumb %}{{ tut.title }}{% endblock %} {% block head %} {% endblock %} {% block iscompatible %} return !!Modernizr.___COMPAT_TEST___ {% endblock %} {% block html5badge %} {% endblock %} {% block content %}
"One of the best things about native apps is that they are full-screen" lots of people, all the time.
It irks me somewhat that this common perception stands. Yes, web pages aren't fullscreen: they have an address bar, usually some other navigational controls. But a lot of modern browsers are pretty good at getting all their junk out of the way pretty quickly.
We have the ability to easily make immersive fullscreen web sites and applications, but like anything on the web there are a couple of ways to do it. This is especially important now that more browsers are supporting an "installed web app" experience which launch fullscreen.
There are several ways that a user or developer can get an web app fullscreen.
You can "fake fullscreen" by auto-hiding the address bar as follows:
window.scrollTo(0,1);
I am telling you this as a friend. It exists, it is a thing, but it is a hack. Please don't use it.
This is a pretty simple method, the page loads and the browser bar is told to get out of the way. Unfortunately it is not standardised and not well supported.  For example browsers often restore the position on the page when the user navigates back to it. Using
window.scrollTooverrides this, which annoys the user. To work around this you have to store the last position in localStorage, and deal with the edge cases (for example, if the user has the page open in multiple windows).
Not all platforms are equal. iOS Safari doesn't have a fullscreen API, but we do on Chrome on Android, Firefox, and IE 11+.
Most applications you build will use a combination of the JS API and the CSS selectors provided by the fullscreen specification.
The main JS API's that you need to care about when building a fullscreen experience are:
element.requestFullscreen()(currently prefixed in Chrome, Firefox, and IE) displays the element in fullscreen mode.
document.exitFullscreen()(currently prefixed in Chrome, Firefox and IE. Firefox uses
cancelFullScreen()instead) cancels fullscreen mode.
document.fullscreenElement(currently prefixed in Chrome, Firefox, and IE) returns true if any of the elements are in fullscreen mode.
You will notice that in the prefixed versions there is a lot of inconsitency between the casing of the 'S' in screen. This is awkward, but this is the problem with specs that are inflight.
When your app is fullscreen you no longer have the browser's UI controls chrome available to you. This changes the way that users interact with your experience. They don't have the standard navigation controls such as Forwards and Backwards; they have their escape hatch that is the Refresh button. It's important to cater for this scenario. You can use some CSS selectors to help you change the style and presentation of your site when the browser enters fullscreen mode.
<button id="goFS">Go fullscreen<button> <script> var goFS = document.getElementById("goFS"); goFS.addEventListener("click", function() { document.body.requestFullscreen(); }, false); </script>
The above example is a little contrived; I've hidden all the complexity around the use of vendor prefixes.

The actual code is a lot more complex. Mozilla has created a very useful script that you can use to toggle fullscreen. As you can see, due to the vendor prefix situation it is rather complex and cumbersome compared to the specified API. Even with the slightly simplified code below, it is still complex.
function toggleFullScreen() { var doc = window.document; var docEl = doc.documentElement; var requestFullScreen = docEl.requestFullscreen || docEl.mozRequestFullScreen || docEl.webkitRequestFullScreen || docEl.msRequestFullscreen; var cancelFullScreen = doc.exitFullscreen || doc.mozCancelFullScreen || doc.webkitExitFullscreen || doc.msExitFullscreen; if(!doc.fullscreenElement && !doc.mozFullScreenElement && !doc.webkitFullscreenElement && !doc.msFullscreenElement) { requestFullScreen.call(docEl); } else { cancelFullScreen.call(doc); } }
We web developers hate complexity. A nice high-level abstract API you can use is Sindre Sorhus' Screenfull.js module which unifies the two slightly different JS API's and vendor prefixes into one consistent API.
Launching a fullscreen web page when the user navigates to it is not possible. Browser vendors are very aware that a fullscreen experience on every page load is a huge annoyance, therefore a user gesture is required to enter fullscreen. Vendors do allow users to "install" apps though, and the act of installing is a signal to the operating system that the user wants to launch as an app on the platform.
Across the major Mobile platforms it is pretty easy to implement using either meta tags, or manifest files as follows.
Ever since the launch of the iPhone, users have been able to install Web Apps to the home screen and have them launch as full-screen web apps.
<meta name="apple-mobile-web-app-capable" content="yes">
If content is set to yes, the web application runs in full-screen mode; otherwise, it does not. The default behavior is to use Safari to display web content. You can determine whether a webpage is displayed in full-screen mode using the window.navigator.standalone read-only Boolean JavaScript property. Apple
The Chrome team has recently implemented a feature that tells the browser to launch the page fullscreen when the user has added it to the home screen. It is similar to the iOS Safari model.
<meta name="mobile-web-app-capable" content="yes">
You can set up your web app to have an application shortcut icon added to a device's homescreen, and have the app launch in full-screen "app mode" using Chrome for Android's "Add to homescreen" menu item. Google Chrome
Firefox OS has implemented a installable web app and packaged app model for developers to create apps for the user's phone. This model is a little more complex, but it fits in to a wider strategy of installable apps. The developer has to define a manifest for the app that Firefox OS will parse at install time.
{ "name": "My App", "description": "My elevator pitch goes here", "launch_path": "/", "icons": { "128": "/img/icon-128.png" }, "fullscreen": true }
If you want to have an "installed app" feel, the "install" API's are the methods you should use, they will integrate far more tightly with the OS than just pure web content for the time being and you will get a seamless fullscreen transiton.
It is natural to think that you take the body element fullscreen, but if you are on a WebKit or Blink based rendering engine you will see it has an odd effect of shrinking the body width to the smallest possible size that will contain all the content (Mozilla Gecko is fine).
To fix this, use the document element instead of the body element:
document.documentElement.requestFullscreen();
To make a video element fullscreen it is exactly the same as making any other element fullscreen.  The recommended way to do this is to have a basic container that wraps the video and the controls that you want the user to see.
<div id="container"> <video><video> <div> <button>Play<button> <button>Stop<button> <button id="goFS">Go fullscreen<button> <div> <div> <script> var goFS = document.getElementById("goFS"); goFS.addEventListener("click", function() { var container = document.getElementById("container"); container.requestFullscreen(); }, false); <script>
This gives you a lot more flexibility because you can combine the container object with the CSS pseudo selector (for example to hide the "goFS" button.)
<style> #goFS:-webkit-full-screen #goFS { display: none; } #goFS:-moz-full-screen #goFS { display: none; } #goFS:-ms-fullscreen #goFS { display: none; } #goFS:fullscreen #goFS { display: none; } <style>
Using these patterns you can detect when full-screen is running and adapt your user interface appropriately:
iOS and Firefox OS don't have a hardware back button or refresh gesture, therefore you must ensure that users can navigate throughout the app without getting locked in.
You can detect if you are running in a fullscreen mode or an installed mode easily on all the major platforms.
if(window.navigator.standalone == true) { // My app is installed and therefore fullscreen }
When launching as an installed app, Chrome is not running in true fullscreen experience so
document.fullscreenElementreturns null and the CSS selectors don't work. Chrome also does not have an API comparable to iOS's navigator.standalone property.
When the user requests fullscreen via a gesture on your site, the standard fullscreen API's are available including the CSS pseudo selector that lets you adapt your UI to react to the fullscreen state like the following
selector:-webkit-full-screen { display: block; // displays the element only when in fullscreen } selector { display: none; // hides the element when not in fullscreen mode }
When the user requests fullscreen via your site or the user launches the app in fullscreen mode all the standard fullscreen API's are available including the CSS pseudo selector that lets you adapt your UI to react to the fullscreen state like the following:
selector:-moz-full-screen { display: block; // hides the element when not in fullscreen mode } selector { display: none; // hides the element when not in fullscreen mode }
In IE the CSS pseudo class lacks a hyphen, but otherwise works similarly to Chrome and Firefox.
selector:-ms-fullscreen { display: block; } selector { display: none; // hides the element when not in fullscreen mode }
The spelling in the specification matches the syntax used by IE.
selector:fullscreen { display: block; } selector { display: none; // hides the element when not in fullscreen mode }
The fullscreen API can be a little finicky sometimes. Browser vendors don't want to lock users in a fullscreen page so they have developed mechanisms to break out of fullscreen as soon as they possibly can. This means you can't build a fullscreen website that spans multiple pages because:
navigator.pushStateAPI will also break out of the fullscreen experience.
You have two options if you want to keep the user in a fullscreen experience:
By using the #syntax to update the url (window.location = "#somestate"), and listening to the window.onhashchange event you can use the browser's own history stack to manage changes in the application state, allow the user to use their hardware back buttons, or offer a simple programmatic back button experience by using the history API as follows:
window.history.go(-1)
There is nothing more annoying to the user than a web site doing something unexpected. When a user navigates to your site don't try and trick them into fullscreen.
Don't intercept the first touch event and issue a requestFullscreen.
If you want to launch apps fullscreen do think about using the install experiences for each platform.
If you plan on offering a fullscreen experience via the installed app mechanisms be considerate to the user:
While we don't have a fully standardised and implemented API, using some of the guidance presented in this article you can easily build experiences that take advantage of the user's entire screen, irrespective of the client.
If you know of any good patterns for full-screen, leave a comment and we can let the world know. If you know of anti-patterns in full-screen let us know so we can update the article to save the frustrations of millions of users on the web.{% endblock %}


Lifecycle of data on BlueMix - The Pulse Sales App Story
This post explores how data that is created from users using mobile apps in a sales scenario ends up useful to the business and can help in improving customer retention or satisfaction or optimizing sales staff. This is illustrated using a combination of BlueMix services that was announced at IBM Pulse
About the scenario
This user scenario is that of the fictional Homestead company that we introduced at IBM Pulse mainstage demo. The sales associates are using the mobile app to help followup with customers, maintain better relations and enhance the overall buying experience. In short they go from being sales helper to personal shopper. Fast forward to year from this launch of this, Homestead has this deployed to several stores and several hundred sales associates are using this app in servicing customers. The need is for the business to reason about this adhoc customer notes that has been captured by the sales associates. The overall context for this post starts with the below cartoon on various interacting roles and system parts.
Step 0: Building the app
The developer at Homestead built the app, that was showcased at IBM Pulse goto 48:43 to see the app
Step 1: Data collection as use increase
As various sales associates use the app, data is being populated on the BlueMix/Cloudant. The structure of the single JSON document as a sales associate interacts with a customer is as follows. See this video that shows a document in data console on the cloud.
{
"lastinteractiondate": "2012-07-11",
"firstname": "Fama",
"lastname": "Stres",
"products": [
"Ski Boots",
"Powerbars"
],
"address": {
"city": "london",
"state": "ny",
"localphone": "3084328"
},
"customerId": "57fea3df-d6f7-467b-8420-ad427c05dafc",
"orders": [
{
"ordid": 15122,
"status": "open",
"comments": "Ship to my home address for the boots",
"filedon": "2012-07-10"
},
{
"ordid": 12920,
"status": "closed",
"comments": "Asked about women's small ski mask",
"filedon": "2012-07-01"
}
]
}
The cartoon describing the interaction/flow is shown below
Step 2: Data ETL into analytics tool
Since this data has been collected over few months, its best to export it to an analytics engine for performing analysis. This is facilitated using IBM DataStage 9.1.2 tool to extract the JSON documents, normalize and map them into tables on the BLU Acceleration service. See the video here
Step 3: Analyzing the data
Now that the data is available on the cloud for analysis using BLU Acceleration service, the business analyst/data scientist can use the power of R to see the customer distribution by state. You can see the video of the interaction here. You can see the normalized tables around customers, orders and products that was created in the previous step in this video. The cartoon describing the interaction/flow is shown below
blog comments powered by Disqus


Recommendations on minimum wage to be submitted by January 2020
Chairman of the National Minimum Wage Advisory Commission, Dr Ronald Robinson, says recommendations on the national minimum wage and the minimum wage for security guards will be submitted to Labour and Social Security Minister, Shahine Robinson, before the end of January 2020.
Robinson said that deliberations on matters arising from the just-concluded public consultations are to begin next week, following which a report will be presented to Labour and Social Security Minister.
She will then make a recommendation to Cabinet that will, eventually, go to Parliament for approval.
Robinson was speaking to JIS News following the final public consultation at the Ministry’s 1F North Street offices in Kingston on Wednesday.
He said that the stakeholders, including the trade unions, the workers and the employees, all agree that the minimum wage needs to be adjusted.
“What is unanimous right across the board, both from the employers and from the workers, is that the current minimum wage is inadequate. So I think it is really what kind of increase and what will go into the increases and the percentages and all those things,” he noted.
Robinson said the consultation sessions, which were also held in St James, Manchester, Portland, and St Ann, had “very good representation from a wide cross-section of individuals”.
“We have gotten invaluable information, presentations, and recommendations from varying groups that will definitely influence our deliberations in moving forward in preparing that report,” he said.
In June 2018, the Government, on the advice of the National Minimum Wage Commission, announced a 12.9 per cent increase in the national minimum wage from $6,200 to $7,000 per week.
In addition, security guards started receiving $9,700, up from $8,854 per week, reflecting a 9.6 per cent increase.
The new rates took effect on August 1, 2018.


In 6 months I have completed a coding bootcamp. It has been a fantastic experience. An experience, where I have become very proficient in HTML, CSS, and JaveScript, as you will see.


"The best preparation for tomorrow is doing your best today."
Chris Younger is an analyst who works with financial services companies to globalize the economy. Chris believes that everyone can be financially stable through discipline and technology. Chris has worked with Common Securitization Solutions to build a universal platform for the issuance and management of mortgage-backed securities. Chris plans to use his development skills to build products in the fintech industry.
I enjoy reading, fitness, and travelling.


Bursa remains negative at mid-afternoon
KUALA LUMPUR, Nov 20 — Bursa Malaysia remained in the negative territory at mid-afternoon on the back of selling in index-linked counters amid weaker regional market performance.
At 3.05pm, the benchmark FTSE Bursa Malaysia KLCI (FBM KLCI) eased 4.16 points to 1,601.15 from 1,605.15 at yesterday's close.
The key index was mainly dragged down by selling in Petronas Chemicals, accounting for 1.415 points. The oil and gas stock fell 10 sen to RM7.26 with 2.78 million shares changing hands.
On the broader market, there were 401 losers and 342 gainers, while 356 counters were unchanged, 909 untraded and 16 others suspended.
Turnover amounted to 1.91 billion shares worth RM1.09 million.
Among the heavyweights, Tenaga lost 10 sen to RM13.66, Public Bank shed two sen to RM19.98, and IHH fell four sen to RM5.41.
Maybank added one sen to RM8.66 while CIMB was flat at RM5.38.
Of the actives, Alam Maritim bagged 2.5 sen to 12.5 sen, Bumi Armada and Tiger Synergy gained two sen each to 55 sen and 9.5 sen respectively, while Fintec inched up half-a-sen to 8.5 sen.
The FBM Emas Index was 9.76 points weaker at 11,359.49, the FBMT 100 Index shed 10.67 points to 11,169.36, the FBM Emas Shariah Index decreased 10.77 points to 11,884.96, and the FBM Ace fell 14.39 points to 4,936.88.
However,the FBM 70 rose 62.0 points to 14,146.14.
Sector-wise, the Plantation Index perked 58.0 points to 7,021.83, but the Financial Services Index contracted 10.72 points to 15,649.66 and the Industrial Products & Services Index slipped 1.1 points to 152.2. — Bernama


Doe Cafe
"; echo strtotime("now"), "\n"; print "This spans\nmultiple lines. The newlines will be\noutput as well."; echo ""; } ?>


Researching as an NSF-Funded Intern in Oldenburg, Germany
This summer, I have been working as an IRES intern in Germany. The NSF IRES Program is a nine week international exchange program where students from the United States are able to experience research in another country.
When I began my Human-Computer Interaction research here in Oldenburg, I first created a timeline for my topic. My topic - researching workload on participants in Virtual Reality and automating the NASA-TLX Questionnaire - was multi-faceted. Many parameters go into the NASA-TLX Questionnaire (see below), so I had to narrow my research question down to just a few to fit my two-month timeline.
I started working with the electroencephalogram (EEG) from Emotiv. I could use this device to gather data on frustration to fit one of the parameters for the NASA-TLX Questionnaire. I started writing a wrapper around the Emotiv BCI Application that would gather this data; however, this would not be integrated well into Unity for Virtual Reality and I abandoned my original idea. As I was about to move on to the next idea, we realized that we were not going to be granted access rights to the Emotiv SDK in a timely manner. Therefore, I moved on to the next piece of hardware: the heart rate monitor. There were, unfortunately, issues with this as well. We were unable to get the SDK for the heart rate monitor nor the proper charging device.
Not all was lost! From this experience of working with the Emotiv EEG, I learned that I am interested in Brain-Computer Interaction. What I found particularly interesting was learning about the science behind how the brain conducts signals to the EEG and how I could capture these signals from the device to create something novel in the virtual sphere.
After some struggles with the hardware and not being able to receive the SDKs, I began to grapple with the aGlass eye-tracking device. The purpose of this device was to measure eye data - in particular, pupil size - to be able to detect when a participant has increased mental workload whilst performing a task in Virtual Reality. Eventually, we were able to get the raw camera data from the aGlass, which we then started connecting to PupilLabs. Due to the difficulties configuring PupilLabs on Windows (we couldn't just run the compiled packages because of the camera settings), we decided to go our way and analyze it from scratch with openCV. The last step then was to integrate into my Unity scene and get a demo study up and running.
While my research experience was not necessarily straightforward, I would not have gone back and picked a different topic, for I learned a great deal over this past summer and my debugging skills have significantly improved because of it.


equals()
call instead,
which does a character-by-character comparison when the strings are different objects.
Example:
void foo(String s, String t) { final boolean b = t == s; }
If t
is known to be non null
, then it's safe to apply "unsafe" quickfix and get the result like:
void foo(String s, String t) { final boolean b = t.equals(s); }


TheShirts-Store
SHIRTS
CONTACT
CART
8
₦5000;
Mc-Mykey Designed Shirt
Select Size
Select
Small
Medium
Large
Add to Cart


UIP
Menu
Create Credentials
Manage Credentials
Attach Email To ID
Verify User
Generate PGP Pair
Upload Documentation
Universal Identity Platform is an algorithm designed to manage the identities of everyone on earth. Through a consensus of authorizing identities and putting them on a blockchain.
Create an ID here
Discover what all the buzz is about!
Our app is available on any mobile device! Download now to get started!
Universal Identity Platform
Are you an organisation of 3 or more?
UIP is an algorithm designed to manage the identities of everyone on earth. Through a consensus of authorizing identities and putting them on a blockchain.
Click gere to create an ID
Manage Credentials
Attach Email To ID
Generate PGP Pair
Create Credentials
Verify User
Upload Documentation


--- layout: default title: Service subtitle: "A handful of the ways I like to get involved in the community around me :)" banner: ../img/banner/banner_4.jpg divsize: half-div divside: right-div permalink: /service/ sitemap: exclude: 'yes' ---
Pint of Science is an international event that brings scientists, community-members, and beer together. Guelph PoS was held over three nights at six different venues in Guelph, and featured 12 different speakers, with talks ranging from bridging the digital divide to food fraud to the science of bubbles and beer.
Twice, while in Rigolet, Labrador doing research with community members we stopped by the local elementary school to teach a couple of the classes how to build websites, and use micro-computers. Once over lunch we had an impromptu jam-session which was the cherry on top of an already great day :)
Attend the non-profit Hillside Festival in Guelph Annually and lend a hand restocking food vendors with amenities, or installing advertisements and directions around town.
Attended the Ontario University Fair to represent the University of Guelph School of Computer Science on three occassions, meeting with potential students and parents to talk about the program at UoG.
Volunteered as a mentor in the Improve Life Challenge, a 24 hour hackathon where participate were tasked with designing a product to support mental health.
Volunteered as a mentor in the Feeding 9 Billion Challenge, a 24 hour hackathon where participate were tasked with designing a product to challenge food-waste and food insecurity.
Led, presented and ran the Guelph Coding Community for the academic year of 2015-2016. The community met biweekly for featured presentors or lecturers, and to share student projects.
Acted as secretary for SOCIS, the student CompSci organization responsible for running student events, trips, outreach and conferences.
Coordinated the 2016 Roboticon Secondary School Competition, where 11 teams competed their robots on a custom mode obstacle course.


Totally Viable is a project by Jacob, Allan & Pasquale. We’re designing and building ideas in public. Here, you can spy on our Slack in real-time. 🕵
Watch us work and subscribe on YouTube.
This site is a work in progress. Let us know if you see any issues.


Customize Process Group Backends Using Cpp Extensions¶
Author: Feng Tian, Shen Li, Min Si
참고
View and edit this tutorial in github.
Prerequisites:
This tutorial demonstrates how to implement a custom ProcessGroup
backend and plug that into
PyTorch distributed package using
cpp extensions. This is helpful when you need a specialized software
stack for your hardware, or when you would like to experiment with new
collective communication algorithms.
Basics¶
PyTorch collective communications power several widely adopted distributed
training features, including
DistributedDataParallel,
ZeroRedundancyOptimizer,
FullyShardedDataParallel.
In order to make the same collective communication API work with
different communication backends, the distributed package abstracts collective
communication operations into a
ProcessGroup
class. Different backends can
then be implemented as subclasses of ProcessGroup
using preferred
third-party libraries. PyTorch distributed comes with three default backends,
ProcessGroupNCCL
, ProcessGroupGloo
, and ProcessGroupMPI
. However,
beyond these three backends, there are also other communication libraries
(e.g., UCC,
OneCCL), different types of hardware
(e.g., TPU,
Trainum), and emerging
communication algorithms (e.g.,
Herring,
Reduction Server).
Therefore, the distributed package exposes extension APIs to allow customizing
collective communication backends.
The 4 steps below show how to implement a dummy ProcessGroup
backend
and use that in Python application code. Please note that this tutorial focuses
on demonstrating the extension APIs, instead of developing a functioning
communication backend. Hence, the dummy
backend just covers a subset of the
APIs (all_reduce
and all_gather
), and simply sets the values of tensors
to 0.
Step 1: Implement a Subclass of ProcessGroup
¶
This first step is to implement a ProcessGroup
subclass that overrides
target collective communication APIs and runs the custom communication algorithm.
The extension also needs to implement a Work
subclass, which
serves as a future of communication results and allows asynchronous execution in
application code. If the extension uses third-party libraries, it can
include the headers and call into the library APIs from the ProcessGroupDummy
subclass. The two code snippets below present the implementation of dummy.h
and
dummy.cpp
. See the dummy collectives
repository for the full implementation.
// file name: dummy.hpp
#include <torch/python.h>
#include <torch/csrc/distributed/c10d/ProcessGroup.hpp>
#include <torch/csrc/distributed/c10d/Work.hpp>
#include <torch/csrc/distributed/c10d/Store.hpp>
#include <torch/csrc/distributed/c10d/Types.hpp>
#include <torch/csrc/distributed/c10d/Utils.hpp>
#include <pybind11/chrono.h>
namespace c10d {
class ProcessGroupDummy : public ProcessGroup {
public:
ProcessGroupDummy(int rank, int size);
c10::intrusive_ptr<Work> allgather(
std::vector<std::vector<at::Tensor>>& outputTensors,
std::vector<at::Tensor>& inputTensors,
const AllgatherOptions& opts = AllgatherOptions()) override;
c10::intrusive_ptr<Work> allreduce(
std::vector<at::Tensor>& tensors,
const AllreduceOptions& opts = AllreduceOptions()) override;
// The collective communication APIs without a custom implementation
// will error out if invoked by application code.
};
class WorkDummy : public Work {
public:
WorkDummy(
OpType opType,
c10::intrusive_ptr<c10::ivalue::Future> future) // future of the output
: Work(
-1, // rank, only used by recvAnySource, irrelevant in this demo
opType),
future_(std::move(future)) {}
// There are several additional helper functions that need to be
// implemented. Please refer to https://github.com/mrshenli/dummy_collectives
// for the full implementation.
private:
c10::intrusive_ptr<c10::ivalue::Future> future_;
};
} // namespace c10d
// file name: dummy.cpp
#include "dummy.hpp"
namespace c10d {
// This is a dummy allgather that sets all output tensors to zero
// Modify the implementation to conduct real communication asynchronously
c10::intrusive_ptr<Work> ProcessGroupDummy::allgather(
std::vector<std::vector<at::Tensor>>& outputTensors,
std::vector<at::Tensor>& inputTensors,
const AllgatherOptions& /* unused */) {
for (auto& outputTensorVec : outputTensors) {
for (auto& outputTensor : outputTensorVec) {
outputTensor.zero_();
}
}
auto future = c10::make_intrusive<c10::ivalue::Future>(
c10::ListType::create(c10::ListType::create(c10::TensorType::get())));
future->markCompleted(c10::IValue(outputTensors));
return c10::make_intrusive<WorkDummy>(OpType::ALLGATHER, std::move(future));
}
// This is a dummy allreduce that sets all output tensors to zero
// Modify the implementation to conduct real communication asynchronously
c10::intrusive_ptr<Work> ProcessGroupDummy::allreduce(
std::vector<at::Tensor>& tensors,
const AllreduceOptions& opts) {
for (auto& tensor : tensors) {
tensor.zero_();
}
auto future = c10::make_intrusive<c10::ivalue::Future>(
c10::ListType::create(c10::TensorType::get()));
future->markCompleted(c10::IValue(tensors));
return c10::make_intrusive<WorkDummy>(OpType::ALLGATHER, std::move(future));
}
} // namespace c10d
Step 2: Expose The Extension Python APIs¶
The backend constructors are called
from Python side,
so the extension also needs to expose the constructor APIs to Python. This can
be done by adding the following methods. In this example, store
and
timeout
are ignored by the ProcessGroupDummy
instantiation method, as
those are not used in this dummy implementation. However, real-world extensions
should consider using the store
to perform rendezvous and supporting the
timeout
argument.
class ProcessGroupDummy : public ProcessGroup {
static c10::intrusive_ptr<ProcessGroup> createProcessGroupDummy(
const c10::intrusive_ptr<::c10d::Store>& store,
int rank,
int size,
const std::chrono::duration<float>& timeout);
static void ProcessGroupDummyConstructor() __attribute__((constructor)) {
py::object module = py::module::import("torch.distributed");
py::object register_backend =
module.attr("Backend").attr("register_backend");
// torch.distributed.Backend.register_backend will add `dummy` as a
// new valid backend.
register_backend("dummy", py::cpp_function(createProcessGroupDummy));
}
}
c10::intrusive_ptr<ProcessGroup> ProcessGroupDummy::createProcessGroupDummy(
const c10::intrusive_ptr<::c10d::Store>& /* unused */,
int rank,
int size,
const std::chrono::duration<float>& /* unused */) {
return c10::make_intrusive<ProcessGroupDummy>(rank, size);
}
PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) {
m.def("createProcessGroupDummy", &ProcessGroupDummy::createProcessGroupDummy);
}
Step 3: Build The Custom Extension¶
Now, the extension source code files are ready. We can then use
cpp extensions
to build it. To do that, create a setup.py
file that prepares the paths and
commands. Then call python setup.py install
to install the extension.
If the extension depends on third-party libraries, you can also specify
libraries_dirs
and libraries
to the cpp extension APIs. See the
torch ucc
project as a real-world example.
# file name: setup.py
import os
import sys
import torch
from setuptools import setup
from torch.utils import cpp_extension
sources = ["src/dummy.cpp"]
include_dirs = [f"{os.path.dirname(os.path.abspath(__file__))}/include/"]
if torch.cuda.is_available():
module = cpp_extension.CUDAExtension(
name = "dummy_collectives",
sources = sources,
include_dirs = include_dirs,
)
else:
module = cpp_extension.CppExtension(
name = "dummy_collectives",
sources = sources,
include_dirs = include_dirs,
)
setup(
name = "Dummy-Collectives",
version = "0.0.1",
ext_modules = [module],
cmdclass={'build_ext': cpp_extension.BuildExtension}
)
Step 4: Use The Extension in Application¶
After installation, you can conveniently use the dummy
backend when calling
init_process_group
as if it is an builtin backend.
import os
import torch
# importing dummy_collectives makes torch.distributed recognize `dummy`
# as a valid backend.
import dummy_collectives
import torch.distributed as dist
os.environ['MASTER_ADDR'] = 'localhost'
os.environ['MASTER_PORT'] = '29500'
dist.init_process_group("dummy", rank=0, world_size=1)
x = torch.ones(6)
dist.all_reduce(x)
print(f"cpu allreduce: {x}")
if torch.cuda.is_available():
y = x.cuda()
dist.all_reduce(y)
print(f"cuda allreduce: {y}")
try:
dist.broadcast(x, 0)
except RuntimeError:
print("got RuntimeError as broadcast is not implemented in Dummy ProcessGroup")


{{ student.sex}} - {{student.age}}
Class : {{student.class}}
Class Teacher : {{student.classTeacher}}
Edit Delete


Lesson 1 Part 2: Vowels, Hard and Soft
There are two types of vowels in Russian: hard and soft. A hard vowel is like a vowel in English, but a soft vowel has y (as in yet) before the vowel sound when the letter appears at the beginning of a word or before another vowel. After a consonant, the vowel has the same sound as its hard variant, and the consonant is softened if this is possible (usually it is). Most vowels come in hard and soft pairs.
|
Hard vowel |
Soft vowel |
Sound of the hard vowel. Soft vowels have y added to the front. |
|
Аa |
Яя |
a as in tall |
|
Ээ |
Ее |
e as in edit |
|
Оо |
Ёё |
o as in orange |
|
Уу |
Юю |
oo as in food |
|
No pair |
Ии |
ee as in feed.
Note that y is not added to the beginning of this letter, as it is unpaired. |
|
Ыы |
No pair |
e as in roses |
|
Йй |
No pair |
y as in yes |
Please note that Ёё is often written as Ее in native Russian texts.
Technically, Ии and Ыы are pairs for the purposes of unsoftenable consonants (see next screen), but have entirely different sounds.
All of the vowels have their independent sound as their name (Ёё= yo), except for Йй, which is known as и краткоя (ee KRAT-kuh-ya), which means short i.
Please also note that Ёё and Оо in unstressed syllables sound like Яя and Аа respectively, and Аа and Яя in unstressed syllables sound like Ээ and Ее respectively.


Party Universe
Save
Load
Reset
Debug
Attendees:
|
Money: $:
|
Clout:
Actions
Dig for Change
Send a Text ($0.25)
Kick Someone Out
Entrance Fee
Door Fee:
+$1
-$1
Supplies
Drinks
Promos
Venues
Phone
Messages
FriendSpace
Create post
Share
End of feed


These instructions can also be found in the file INSTALL.
INSTALL
I have tested this on Debian Linux systems (woody and sid), Solaris 2.6 and 2.7. Others have successfully compiled it on Windows and NT.


October 29
Beloved, now are we the sons of God, and it doth not yet appear what we shall be: but we know that, when he shall appear, we shall be like him; for we shall see him as
he is. And every man that hath this hope in him purifies himself, even as he is pure. 1 John 3:2-3
Hopelessness. As this age draws to a close, that's a feeling that's going to be more and more common among the people of this world. But, you know, it's something we as believers never have to feel! Because no matter how much pressure comes on the earth, no matter how dark the natural circumstances around us are, we know that we have hope in the soon return of the Lord Jesus Christ.
Sometimes we forget that. We get our attention focused so intently on the natural things of this life that we lose that hope and get caught up in the hopelessness around us. But we don't have to let that happen. A friend of mine once met a born again Arab woman in the Middle East who was living proof of that. The woman was caught in a life most of us would consider almost unbearable. She was living in a war zone that had been torn up by violence. She faced the danger of bombs and bullets every day.
Now that Arab woman had no hope in the natural. Her country was being destroyed around her. She had to go to Israel to work and get money for her family because there were no jobs where she was, no way to make money. Things around her seemed to be going from bad to worse, but she told my friend she had hope because she knew that Jesus was coming back for her. And that hope kept her going. So, if you're feeling hopeless, get your eyes off this world and get them on the soon return of Jesus. Not only will that raise your spirit, the Bible says it will purify you. It will cause you to live uprightly, to separate you from the sin and failure of the world around you. It will lift you into the joy and victory of God.
Think about this. When this old world comes to an end, you and I will just be getting started. We'll be stepping into the most glorious life we've ever known. The people of the world may look back wistfully and wish for better days gone by. But for you and me, the best is yet to come. So we can shout hallelujah in the midst of trouble and say with the Apostle John, "Even so, come, Lord Jesus." Come quickly!
Scripture Reading: Revelation 21, 22:1-7


Seems your browser doesn't support Javascript! Websockets rely on Javascript being enabled. Please enable Javascript and reload this page!
Connect
SEND