30sGuess: 30 seconds to Guess the song!
Log out
by
Submit!
Volume:
Score:
0
/
0
Guess song/artist in...
30-21 seconds left: 5 points (per correct answer)
20-11 seconds left: 2.5 poins (per correct answer)
10-1 second(s) left: 2.5 poins (per correct answer)


About Me
- Name
-
- Johnny Huang
- 黄智强
- Location
-
- Shanghai, China
- Education
-
- 2006.09 - 2010.06, Zhejiang University, Computer Science, BS, Hangzhou, China
- 2010.09 - 2013.03, Shanghai Jiao Tong University, Computer Science, MS, Shanghai, China


apps
https://purplepromise.xyz
https://lex.purplepromise.xyz
Alexa Companion App
alexa and lex
https://developer.amazon.com
https://aws.amazon.com
other
https://pubnub.com
https://twilio.com
https://digitalocean.com


Hardware:
So reading the wikipedia entry for chip8 we know that the chip8 system is made of the following:
- Memory of 0xFFF bytes
- 16 8-Bit data registers, called V0 to VF. VF doubles as the carry flag
- 16 Bit address register I which is used to access memory
- 16 Bit program counter and a stack
Hardware Emulation:
So to emulate the chip8 we need variables of sizes 8-bit (1 byte) and 16-bits(2 bytes, or 1 word). A type char is 1 byte long and short int is 1 word long which will give us the following typedefs:
typedef unsigned char BYTE;
typedef unsigned short int WORD;
We know from our hardware specification that the following variables is what we need to emulate the chip8 hardware:
BYTE m_GameMemory[0xFFF] ; // 0xFFF bytes of memory
BYTE m_Registers[16] ; // 16 registers, 1 byte each
WORD m_AddressI ; // the 16-bit address register I
WORD m_ProgramCounter ; // the 16-bit program counter
std::vector
Now we have our hardware variables it is time to initialize them. Wikipedia says that the game is loaded into memory 0x200 as 0-1FFF is for the interpreter. So all we need to do is load the game into 0x200 and initialize the other variables. Remember that the program counter is the variable used to point to which part of memory we are currently executing so this needs to be set to the first instruction of the game which will be address 0x200
void CPUReset( )
{
m_AddressI = 0 ;
m_ProgramCounter = 0x200 ;
memset(m_Registers,0,sizeof(m_Registers)) ; // set registers to 0
// load in the game
FILE *in;
in = fopen( "c:/INVADERS", "rb" );
fread( &m_GameMemory[0x200], 0xfff, 1, in);
fclose(in);
}
Graphic Emulation:
The graphics work by drawing sprites at a specific X and Y position on screen. The X and Y coordinates refer to the top left pixel of the sprite. Every sprite has a width of 8 pixels and a variable height. Sprite data is stored in game memory at the address the I register points to. Each byte of this memory represents 1 line of the sprite to draw. As just stated each line is always 8 pixels wide meaning that each pixel can be represented by 1 bit in the byte. If the bit for the pixel is set to 0 it means ignore this pixel leaving it at its current state. If the bit is set to 1 then it means toggle the state of the pixel (if it is currently on then set it to off otherwise set it to on). If the pixel is toggled from on to off then the flag register gets set to 1 otherwise it will be set to 0. This will represent a collision in sprites. Opcode DXYN is responsible for the graphic drawings. The resolution of the display is 64x32 and can be represented in the emulator as a 2D array.
BYTE m_ScreenData[64][32] ;
Of course a resolution of 64x32 is pretty small so you can scale it however you like when you actually come to drawing the screen data. This is enough information to emulate the chip8 graphics however feel free to head over to David Winters site for a more indepth look at the chip8 graphics. The implementation of the opcode DXYN is discussed in the Example Opcode section of this site. You can use the navigation bar to your right to move on the next step, the fetch and decode loop


--- layout: default lang: en ---
Established in 2007 by Mr. Yoshifumi Hashimoto with the dream of bridging Asian countries, BridgeRoots is a comprehensive law firm that provides legal services across a wide range of disciplines.  With more than 60 multilingual lawyers in 5 offices throughout Asia and our combined effort from our oversea business partners from China and Korea, our services provide the highest standard of excellence to exceed your expectations.
General legal affairs and accounting
With a team of professional and experienced lawyers and CPAs, we provide a one stop service in general corporate legal and accounting.
Subject experts
Our subject experts covers varies of business fields such as: tax, IP, HR, real estate, certification, etc.
Our goal is to protect what's important to our customers
We strive to provide solutions that not only will fulfill a short term need, but is also optimal to your long term interests.
Our service network covers Japan, China and Korea
We have an office in Shanghai, China, specializing in international business (Japan <-> China, Japane <-> Korea). We also partner with many local law firms in China and Korea to provide prompt and accurate legal services.
{{ item.description }}


GitHub API status:
Committed
Welcome to Git (version 2.0.2)
If this is your first time here, please run 'git help'
Run 'git info' for more information about Committed
Enter a username to get information on a user
Committed@COMMITTED-WEB ~
$
Their most popular repos


---
title: Orbit
layout: component.html
---
***
{{> examples_orbit_basic}}
***
Deprecation Notice:
Orbit has been deprecated, meaning that it is no longer supported. There's no need to worry though as we decided to leave it in Foundation if you choose to continue using it. We explain it here.
There are other great options if you need an image slider. A lot of them have features based on Orbit and may have added one of two more features.
This image slider is really slick: Slick Carousel. It has all the features Orbit has and can also be used as a carousel for single image sliding. It's easy to set up and is well supported.
Orbit is also not accessible to screen readers or assistive devices.
***
## How to Setup Orbit
Orbit requires minimal HTML markup to function. Our Javascript takes care of most of the heavy lifting for you. The only thing you need to do is add a `` element to your page. You can then populate it with images, text, and captions. Here's the markup required to implement a basic Orbit slider on your page:
HTML
{{#markdown}}
```html
{{> examples_orbit_basic}}
```
{{/markdown}}
Rendered HTML
{{#markdown}}
```html
{{> examples_orbit_basic_rendered}}
```
{{/markdown}}
***
## Content Sliders
Orbit can also be used with just content and no images.
HTML
{{#markdown}}
```html
{{> examples_orbit_content}}
```
{{/markdown}}
Rendered HTML
{{> examples_orbit_content}}
***
## Deep Linking
To link to a particular slide in your Orbit slider you will need to add a `data-orbit-slide` attribute to each slide. Then anywhere on your page you can use `data-orbit-link` to link to that slide.
***
## Accessibility
This component is not yet accessible. Stay tuned for updates in future releases.
***
## Customize with Sass
We've included a bunch of variables that you'll be able to use if you're into getting SASSy with things.
{{#markdown}}
```scss
$include-html-orbit-classes: $include-html-classes !default;
// We use these to control the caption styles
$orbit-container-bg: none !default;
$orbit-caption-bg: rgba(51,51,51, 0.8) !default;
$orbit-caption-font-color: $white !default;
$orbit-caption-font-size: rem-calc(14) !default;
$orbit-caption-position: "bottom" !default; // Supported values: "bottom", "under"
$orbit-caption-padding: rem-calc(10 14) !default;
$orbit-caption-height: auto !default;
// We use these to control the left/right nav styles
$orbit-nav-bg: transparent !default;
$orbit-nav-bg-hover: rgba(0,0,0,0.3) !default;
$orbit-nav-arrow-color: $white !default;
$orbit-nav-arrow-color-hover: $white !default;
// We use these to control the timer styles
$orbit-timer-bg: rgba(255,255,255,0.3) !default;
$orbit-timer-show-progress-bar: true !default;
// We use these to control the bullet nav styles
$orbit-bullet-nav-color: $iron !default;
$orbit-bullet-nav-color-active: $aluminum !default;
$orbit-bullet-radius: rem-calc(9) !default;
// We use these to controls the style of slide numbers
$orbit-slide-number-bg: rgba(0,0,0,0) !default;
$orbit-slide-number-font-color: $white !default;
$orbit-slide-number-padding: rem-calc(5) !default;
// Graceful Loading Wrapper and preloader
$wrapper-class: "slideshow-wrapper" !default;
$preloader-class: "preloader" !default;
// Hide controls on small
$orbit-nav-hide-for-small: true !default;
$orbit-bullet-hide-for-small: true !default;
$orbit-timer-hide-for-small: true !default;
```
{{/markdown}}
***
## Configuring Orbit
It's easy to configure Orbit using our provided Javascript. You can use with data-attributes or plain old Javascript. Make sure `jquery.js`, `foundation.js`, and `foundation.orbit.js` have been included on your page before continuing. For example add the following before the closing `` tag:
```html
```
### Basic
Using data-attributes is the preferred method of making changes to our Javascript.
```html
```
### Advanced
You can also adjust settings using plain old Javascript. Here's all the available settings:
#### JS
```js
$(document).foundation({
orbit: {
animation: 'slide', // Sets the type of animation used for transitioning between slides, can also be 'fade'
timer_speed: 10000, // Sets the amount of time in milliseconds before transitioning a slide
pause_on_hover: true, // Pauses on the current slide while hovering
resume_on_mouseout: false, // If pause on hover is set to true, this setting resumes playback after mousing out of slide
next_on_click: true, // Advance to next slide on click
animation_speed: 500, // Sets the amount of time in milliseconds the transition between slides will last
stack_on_small: false,
navigation_arrows: true,
slide_number: true,
slide_number_text: 'of',
container_class: 'orbit-container',
stack_on_small_class: 'orbit-stack-on-small',
next_class: 'orbit-next', // Class name given to the next button
prev_class: 'orbit-prev', // Class name given to the previous button
timer_container_class: 'orbit-timer', // Class name given to the timer
timer_paused_class: 'paused', // Class name given to the paused button
timer_progress_class: 'orbit-progress', // Class name given to the progress bar
slides_container_class: 'orbit-slides-container', // Class name given to the slide container
preloader_class: 'preloader', // Class given to the preloader
slide_selector: 'li', // Default is '*' which selects all children under the container
bullets_container_class: 'orbit-bullets',
bullets_active_class: 'active', // Class name given to the active bullet
slide_number_class: 'orbit-slide-number', // Class name given to the slide number
caption_class: 'orbit-caption', // Class name given to the caption
active_slide_class: 'active', // Class name given to the active slide
orbit_transition_class: 'orbit-transitioning',
bullets: true, // Does the slider have bullets visible?
circular: true, // Does the slider should go to the first slide after showing the last?
timer: true, // Does the slider have a timer active? Setting to false disables the timer.
variable_height: false, // Does the slider have variable height content?
swipe: true,
before_slide_change: noop, // Execute a function before the slide changes
after_slide_change: noop, // Execute a function after the slide changes
prev_text: 'Previous slide', // (Title) text for arrow to previous slide
next_text: 'Next slide' // (Title) text for arrow to next slide
}
});
```
***
## Real World Example
Javascript
{{#markdown}}
```js
$(document).foundation({
orbit: {
animation: 'slide',
timer_speed: 1000,
pause_on_hover: true,
animation_speed: 500,
navigation_arrows: true,
bullets: false
}
});
```
{{/markdown}}
HTML
{{#markdown}}
```html
```
{{/markdown}}
***
## Events
There are several events that you can bind to in Orbit. Here's an example of how you can bind to these events:
#### HTML
```html
```
#### JS
```js
$("#featured1").on("ready.fndtn.orbit", function(event) {
console.info("ready");
});
$("#featured1").on("before-slide-change.fndtn.orbit", function(event) {
console.info("before slide change");
});
$("#featured1").on("after-slide-change.fndtn.orbit", function(event, orbit) {
console.info("after slide change");
console.info("slide " + orbit.slide_number + " of " + orbit.total_slides);
});
$("#featured1").on("timer-started.fndtn.orbit", function(event, orbit) {
console.info("timer started");
});
$("#featured1").on("timer-stopped.fndtn.orbit", function(event, orbit) {
console.info("timer stopped");
});
```
***
### Adding New Content After Page Load
If you add new content after the page has been loaded, you will need to reinitialize the Foundation JavaScript by running the following:
{{#markdown}}
```javascript
$(document).foundation();
```
{{/markdown}}
Reflow will make Foundation check the DOM for any elements and re-apply any listeners to them.
{{#markdown}}
```javascript
$(document).foundation('orbit', 'reflow');
```
{{/markdown}}
***
### Sass Errors?
If the default "foundation" import was commented out, then make sure you import this file:
SCSS
{{#markdown}}
```scss
@import "foundation/components/orbit";
```
{{/markdown}}


on what the Buddha taught
Ājīva is often translated as livelihood.
And it certainly has to do with livelihood. In the discourses particulars of ājīva very often includes jobs. But also found are things like: ‘With right action, right ājīva; with wrong action, wrong ājīva’. Thus a foolish person has, despite their job, wrong ājīva (AN10.105).
Then, to put a little less emphasis on just income while trying to incorporate 'life' (jīva) we could use ‘way of life’ instead. And it does connect:
With right view, right attitude; with right attitude, right speech; with right speech, right doing; with right doing, right way of life.
Ājīva [ā+jīva] way of life.


{% extends 'base.html' %} {% import 'bootstrap/wtf.html' as wtf %} {% block content %}
Create new account
If you already have an account click here to sign in


@() @base("Ethics") {
All research on humans conducted on Curtin University campus, or by Curtin University staff or students must be approved by the Curtin Human Research Ethics Committee before it can commence. Non-compliance with this requirement represents research misconduct which will be investigated.


|
||||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Object edu.biu.scapi.comm.PlainChannel edu.biu.scapi.comm.PlainTCPChannel
public class PlainTCPChannel
This class represents a concrete channel in the Decorator Pattern used to create Channels. This channel ensures TCP type of communication. In order to enforce the right usage of the Channel class we will restrict the ability to instantiate one, only to classes within the Communication Layer’s package. This means that the constructor of the channel will be unreachable from another package. However, the send, receive and close functions will be declared public, therefore allowing anyone holding a channel to be able to use them.
| Nested Class Summary | |
|---|---|
static class |
PlainTCPChannel.Message
A nested class to use in the send and receive functions. |
| Nested classes/interfaces inherited from class edu.biu.scapi.comm.PlainChannel |
|---|
PlainChannel.State |
| Method Summary | |
|---|---|
void |
close()
Closes the socket and all other used resources. |
boolean |
isClosed()
|
java.io.Serializable |
receive()
Receives the message sent by the other end-user of the channel. |
void |
send(java.io.Serializable msg)
Sends the message to the other end-user of the channel with TCP protocol. |
| Methods inherited from class java.lang.Object |
|---|
equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
| Method Detail |
|---|
public void send(java.io.Serializable msg) throws java.io.IOException
msg
- the object to send
java.io.IOException
- Any of the usual Input/Output related exceptions.public java.io.Serializable receive() throws java.lang.ClassNotFoundException, java.io.IOException
java.lang.ClassNotFoundException
- The Class of the serialized object cannot be found
java.io.IOException
- Any of the usual Input/Output related exceptionspublic void close()
public boolean isClosed()
|
||||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |


The setDataMoveAttr function specifies if the input data can be read from other nodes.
This function does not return any value.
In certain situation, by reading data only from its location node may speed up the process.


This week's Search Inside Yourself chapter introduces us to mindfulness conversation concept.
READ MORE »
This week's Search Inside Yourself chapter introduces us to mindfulness conversation concept.
This week we've taken a look at the concept of Responsive Design and Mobile First Design, what pro and cons for using Frameworks and creating wireframe of our blog. Wow.
Getting to know different technique of time management and how to improve yourself by adding good habits in your daily life.
Watched a really interesting talk done by a guy named Shereef, who started Dev Bootcamp in U.S. This post is about my reflection on his talk.


PyMieSim
Navigation
index
Theory
|
Code
|
Examples
|
Material
|
LPModes
|
References
|
search
|
Source code structures
Source code structures
¶
Source
¶
PlaneWave
¶
GaussianBeam
¶
Scatterer
¶
Sphere
¶
Cylinder
¶
WMSample
¶
Detector
¶
Photodiode
¶
LPmode
¶
Table of Contents
Source code structures
Source
PlaneWave
GaussianBeam
Scatterer
Sphere
Cylinder
WMSample
Detector
Photodiode
LPmode
This Page
Show Source
Quick search
Navigation
index
Theory
|
Code
|
Examples
|
Material
|
LPModes
|
References
|
search
|
Source code structures


--- layout: post title: Determining which web browser feature is cross-browser compatible permalink: determining-which-web-browser-feature-is-cross-browser-compatible/ date: 2013-05-28 00:44:43.000000000 +08:00 categories: - coding tags: [] status: draft type: post published: false meta: _edit_last: '2' cleaned: true ---
http://caniuse.com/


BatteryGuru helps you track usage and optimize battery health for longevity
by Aamir SiddiquiPractically all smartphones these days come with non-removable batteries and some form of fast charging technology. Unless done properly with adequate heat management, charging and fast charging do degrade the life of your phone’s battery, and non-removable batteries make it difficult to swap out an older degraded battery for a new one. Glass sandwich designs further complicate the swapping process, often cracking either the front or the back glass if you are not experienced enough. In these situations, it becomes really important to maintain the health of your battery, especially if you plan to use your phone for more than 2 years. BatteryGuru attempts to help you in this endeavor.
BatteryGuru by XDA Recognized Developer Paget96 tries to help your phone’s battery life by focusing on its overall longevity rather than getting you the most work done with a full charge.
The main info screen on BatteryGuru has sections to show different charging statistics, like charge/discharge percentage, estimated time for full charge/discharge, info on deep sleep and more. The “Protection” section is where users can set reminders for charging limits and battery temperature, which is what will directly affect how long your phone’s battery will last. You can tweak the settings to be more aggressive or laidback, depending on your needs and expectations. The “Health” section contains information and tips for battery longevity, while the “Save” section toggles different hardware settings to save battery.
BatteryGuru doesn’t require root, and the developer assures that it also does not access any sensitive information, and it will not show false info to the user. The app is free and can be downloaded from the Play Store.


Summary: A simple crypto challenge requiring basic scripting skills and some knowledge of RSA encryption.
Starting this challenge off we are given a text file with the following large numbers in it.
Looking through RSA's wikipedia page specifically the decryption section, the following formula tells us how to use these numbers to decrypt the message!
So all we need to do is power d to c and then modulus the result with n, this can be achieved with a simple python script! Let's run the script and see what output we get!
And looks like it decoded to hex, all we have to do is use this hex converter to get the flag!


Buttons are used as triggers for actions. Depending on the use case, buttons contain a label and/or an icon. There are a variety of styles, sizes, and variations that can be used for different situations.
All button labels are sentence case. They should be as short as possible while clearly explaining what will happen when the button is clicked.
Button styles
There are 6 button styles:
Default, the general button style.
Primary, indicates the critical, or most important action on a form/page.
Danger, indicates a dangerous, generally destructive action, such as deleting.
Success, indicates a positive action.
Warning, indicates an action that may have some side effects, such as giving a user admin access.
Link, used for non-critical actions. Useful for keeping the interface simple.
All buttons are prefixed with the btn class. The btn class can be applied to any element. Try to use <button> elements when an action won’t change the URL/route, and <a> elements when the action will change the URL/route.
Disabled state
Button sizes
There are 4 different button sizes:
Large, use the btn-lg class.
Normal, no extra classes necessary.
Small, use the btn-sm class.
Extra small, use the btn-xs class.
Block level buttons
Use the btn-block class for buttons that fill the width of their container. These are useful for narrow containers and cleaning up alignment.
Button groups
Related buttons can be grouped together to show associations and improve clarity. Button groups can be sized using the btn-group-lg, btn-group-sm, and btn-group-xs classes.
Toggle buttons
Similar to a checkbox, toggle buttons can be toggled between active or not active.
Add the active class and the aria-pressed="true" attribute to a button.
Dropdown buttons
Dropdown buttons can provide a menu or popover when clicked.
Split buttons contain both a button and a dropdown. Clicking the button performs the action. Clicking the dropdown reveals other actions. Generally, the button is the primary or most common action, and items in the dropdown are secondary or less common actions.
Icon buttons are buttons with an icon inside. An icon button may or may not have text. Icon buttons can help save space or improve the ability to scan/find buttons quickly.
Use btn-icon-only for buttons with only an icon in it. This optimizes the padding.


Jong Lee
Tufts University
Computer Science
Junior
Hi and welcome to my page! I was born in South Korea, raised in New Jersey, and currently reside in Medford, MA as an undergraduate at Tufts University. In my spare time, I like to work on coding projects, play video games, and play guitar. Feel free to connect with me on any social medias listed below.
View Resume


We interviewed women in San Francisco and discovered that most of them are actually avoiding shopping at malls, and opting for more time efficient solutions, like Amazon and Target. We also learned that some people plan for their shopping trips, and everyone likes sales.
My team member made a User Persona to describe a young professional, who lives in San Francisco, works full time, and is taking night classes. She likes shopping at malls, but being so busy, she normally shops online.
My team member created this User Journey to demonstrate Christine's shopping struggles.
Bargain hunting at the mall is just not a time efficient experience.
I made this Storyboard to demonstrate the easy time Christine could have bargain hunting with the app we decided to design, by simply selecting the stores she wanted to visit of those having sales at the mall, and following a suggested shopping itinerary for an efficient trip.
Some of the future feature considerations we had were a real-time nearby sale feature, a compare products feature, a Google Maps an ability to save your search, and ability to share the shopping itinerary.


Many of the modelling examples have a java program as SUT.
Please consult the java program section for instruction on working with java programs.
We want to test our java program StimulusResponse.java.
This is a simple program that receives an input (Stimulus) and responds to it (Response).
All the files used in this example can be found at the example folder.
This program (our System Under Test - SUT) receives a stimulus and responds to it. Let’s define the channels needed for modelling this behaviour:
CHANDEF Chans ::= Stimulus; Response
ENDDEF
The model should specify that the system uses two channels, one incoming for the stimulus and one outgoing for the response.
It should also specify that first a stimulus and then a response are communicated.
The Model Definition of this system in TorXakis is as follows:
MODELDEF Model ::=
CHAN IN Stimulus
CHAN OUT Response
BEHAVIOUR
Stimulus >-> Response
ENDDEF
Our SUT communicates with the outside world by sending and receiving lines i.e. strings terminated by a line feed, over a socket at port 7890.
When TorXakis and the SUT run on the same machine (localhost) the SUT connection can be defined in TorXakis as follows:
CNECTDEF Sut ::=
CLIENTSOCK
CHAN OUT Stimulus HOST "localhost" PORT 7890
ENCODE Stimulus -> ! ""
CHAN IN Response HOST "localhost" PORT 7890
DECODE Response <- ? s
ENDDEF
$> java StimulusResponse
$> torxakis StimulusResponse.txs
tester Model Sut
test 3
TorXakis will perform the two communication actions, Stimulus and Response,
observe that the system under test communicates no additional output until
TorXakis times out (as expected), and finally conclude:
TXS >> .....1: IN: Act { { ( Stimulus, [] ) } }
TXS >> .....2: OUT: Act { { ( Response, [] ) } }
TXS >> .....3: OUT: No Output (Quiescence)
TXS >> PASS
$> java StimulusNoResponse
$> torxakis StimulusResponse.txs
tester Model Sut
test 3
TorXakis will perform the first communication action: Stimulus.
TorXakis will observe that the expected second communication action (Response) doesn’t occur,
causing the step to time out, so conclude:
TXS >> .....1: IN: Act { { ( Stimulus, [] ) } }
TXS >> .....2: OUT: No Output (Quiescence)
TXS >> Expected:
TXS >> [ ( { Response[] }, [], [] ) ]
TXS >> FAIL: No Output (Quiescence)
Let’s change our system to run in a loop of waiting for next Stimulus, instead of exiting after the first one. See StimulusResponseLoop.java for the updated Java code.
Our channel definitions don’t change:
CHANDEF Model ::= Stimulus, Response
ENDDEF
Our SUT connection stays the same, too:
CNECTDEF Sut ::=
CLIENTSOCK
CHAN OUT Stimulus HOST "localhost" PORT 7890
ENCODE Stimulus -> ! ""
CHAN IN Response HOST "localhost" PORT 7890
DECODE Response <- ? s
ENDDEF
In our model definition, we need a way to define the looping behaviour. We can make use of a recursive procedure definition for this:
PROCDEF stimResp [ Stimulus, Response ] ()
::=
Stimulus >-> Response >-> stimResp [Stimulus,Response] ()
ENDDEF
Now we can use this procedure definition in our Model:
MODELDEF Model ::=
CHAN IN Stimulus
CHAN OUT Response
BEHAVIOUR
stimResp [Stimulus,Response] ()
ENDDEF
Now we can run model based tests on test our new SUT:
$> java StimulusResponseLoop
$> torxakis StimulusResponseLoop.txs
tester Model Sut
test 10
TorXakis will perform the two communication actions, Stimulus and Response,
over and over again for as many test steps as we tell it to (in this example: 10).
Observing that SUT communicates a Response for every Stimulus as expected,
it will finally conclude:
TXS >> .....1: IN: Act { { ( Stimulus, [] ) } }
TXS >> .....2: OUT: Act { { ( Response, [] ) } }
TXS >> .....3: IN: Act { { ( Stimulus, [] ) } }
TXS >> .....4: OUT: Act { { ( Response, [] ) } }
TXS >> .....5: IN: Act { { ( Stimulus, [] ) } }
TXS >> .....6: OUT: Act { { ( Response, [] ) } }
TXS >> .....7: IN: Act { { ( Stimulus, [] ) } }
TXS >> .....8: OUT: Act { { ( Response, [] ) } }
TXS >> .....9: IN: Act { { ( Stimulus, [] ) } }
TXS >> ....10: OUT: Act { { ( Response, [] ) } }
TXS >> PASS
Let’s say we want to build a simple system that that receives an input and repeats it as is (AKA echoes it). Before writing any code for it, we’re going to model the solution and test it with TorXakis.
The complete model file used in this example can be found at the example folder.
This system is going to receive an input and echo it via the output.
For simplicity, let’s limit the inputs to only be integers. We can define the channels needed for modelling this behaviour as:
CHANDEF Chans ::= In, Out :: Int
ENDDEF
We need to define the process of receiving the input and communicating it to the output channel. Here is our process definition:
PROCDEF proc [ In, Out :: Int ] ( ) ::=
In ? x
>-> Out ! x
>-> proc [ In, Out ] ()
ENDDEF
The model should specify that the system uses two channels, one incoming and one outgoing.
It should also specify that first an input and then an output are communicated.
The behaviour of the model should be the process that is defined above.
The Model Definition of this system in TorXakis is as follows:
MODELDEF Model ::=
CHAN IN In
CHAN OUT Out
BEHAVIOUR proc [ In, Out ] ( )
ENDDEF
We don’t have any SUT yet, but with TorXakis we can already step through the model to verify it.
$> torxakis Echo.txs
stepper Model
step 10
TorXakis will perform the two communication actions with random integer inputs and display behaviour of the model at every step.
After required number of steps are reached, TorXakis will conclude:
TXS >> .....1: Act { { ( In, [ -59 ] ) } }
TXS >> .....2: Act { { ( Out, [ -59 ] ) } }
TXS >> .....3: Act { { ( In, [ -50 ] ) } }
TXS >> .....4: Act { { ( Out, [ -50 ] ) } }
TXS >> .....5: Act { { ( In, [ -67 ] ) } }
TXS >> .....6: Act { { ( Out, [ -67 ] ) } }
TXS >> .....7: Act { { ( In, [ -7 ] ) } }
TXS >> .....8: Act { { ( Out, [ -7 ] ) } }
TXS >> .....9: Act { { ( In, [ -77 ] ) } }
TXS >> ....10: Act { { ( Out, [ -77 ] ) } }
TXS >> PASS
We still don’t have the real implementation of the system, but with TorXakis we don’t need it to mimic an actual test with an existing SUT.
TorXakis is capable of simulating the SUT based on the defined model. We just have to define the connection to be used by the Simulator:
CNECTDEF Sim ::=
SERVERSOCK
CHAN IN In HOST "localhost" PORT 9999
DECODE In ! fromString(s) <- ? s
CHAN OUT Out HOST "localhost" PORT 9999
ENCODE Out ? i -> ! toString(i)
ENDDEF
Important points:
Now we have a (simulated) SUT, so we can connect to it and execute Model Based Testing!
TorXakis is going to communicate with the SUT by sending and receiving lines i.e. strings terminated by a line feed, over a socket at port 9999.
When TorXakis and the SUT run on the same machine (localhost) the SUT connection can be defined in TorXakis as follows:
CNECTDEF Sut ::=
CLIENTSOCK
CHAN OUT In HOST "localhost" PORT 9999
ENCODE In ? i -> ! toString(i)
CHAN IN Out HOST "localhost" PORT 9999
DECODE Out ! fromString(s) <- ? s
ENDDEF
Important points:
$> torxakis Echo.txs
simulator Model Sim
TorXakis will start waiting for a connection, in order to start the Simulator.
$> torxakisPort 9877 Echo.txs
tester Model Sut
As soon as you enter this command, you’ll see that Simulator also responds:
TXS >> Simulator started
param param_Sim_deltaTime 5000
param param_Sut_deltaTime 5000
sim 20
test 10
TorXakis will test the (simulated) SUT with random integer inputs and display behaviour of the SUT at every step.
After required number of steps are reached, TorXakis will conclude:
TXS >> .....1: IN: Act { { ( In, [ 1 ] ) } }
TXS >> .....2: OUT: Act { { ( Out, [ 1 ] ) } }
TXS >> .....3: IN: Act { { ( In, [ 14 ] ) } }
TXS >> .....4: OUT: Act { { ( Out, [ 14 ] ) } }
TXS >> .....5: IN: Act { { ( In, [ -82 ] ) } }
TXS >> .....6: OUT: Act { { ( Out, [ -82 ] ) } }
TXS >> .....7: IN: Act { { ( In, [ -67 ] ) } }
TXS >> .....8: OUT: Act { { ( Out, [ -67 ] ) } }
TXS >> .....9: IN: Act { { ( In, [ -4 ] ) } }
TXS >> ....10: OUT: Act { { ( Out, [ -4 ] ) } }
TXS >> PASS
And simulator TorXakis instance will be acting as the SUT:
TXS >> .....1: OUT: No Output (Quiescence)
TXS >> .....2: IN: Act { { ( In, [ 1 ] ) } }
TXS >> .....3: OUT: Act { { ( Out, [ 1 ] ) } }
TXS >> .....4: IN: Act { { ( In, [ 14 ] ) } }
TXS >> .....5: OUT: Act { { ( Out, [ 14 ] ) } }
TXS >> .....6: OUT: No Output (Quiescence)
TXS >> .....7: IN: Act { { ( In, [ -82 ] ) } }
TXS >> .....8: OUT: Act { { ( Out, [ -82 ] ) } }
TXS >> .....9: OUT: No Output (Quiescence)
TXS >> ....10: IN: Act { { ( In, [ -67 ] ) } }
TXS >> ....11: OUT: Act { { ( Out, [ -67 ] ) } }
TXS >> ....12: OUT: No Output (Quiescence)
TXS >> ....13: IN: Act { { ( In, [ -4 ] ) } }
TXS >> ....14: OUT: Act { { ( Out, [ -4 ] ) } }
TXS >> ....15: OUT: No Output (Quiescence)
TXS >> ....16: OUT: No Output (Quiescence)
TXS >> ....17: OUT: No Output (Quiescence)
TXS >> ....18: OUT: No Output (Quiescence)
TXS >> ....19: OUT: No Output (Quiescence)
TXS >> ....20: OUT: No Output (Quiescence)
TXS >> PASS
TorXakis is capable of XML-based communication with SUT’s and simulating them as well.
Let’s define another SUT connection and a simulator, both of which use XML-based communication.
CNECTDEF Xut ::=
CLIENTSOCK
CHAN OUT In HOST "localhost" PORT 9999
ENCODE In ? i -> ! toXml(i)
CHAN IN Out HOST "localhost" PORT 9999
DECODE Out ! fromXml(s) <- ? s
ENDDEF
CNECTDEF Xim ::=
SERVERSOCK
CHAN IN In HOST "localhost" PORT 9999
DECODE In ! fromXml(s) <- ? s
CHAN OUT Out HOST "localhost" PORT 9999
ENCODE Out ? i -> ! toXml(i)
ENDDEF
Now we can simulate and test our proposed system as if it uses XML-Based communication:
$> torxakis Echo.txs
simulator Model Xim
$> torxakisPort 9877 Echo.txs
tester Model Xut
param param_Sim_deltaTime 5000
param param_Sut_deltaTime 5000
sim 20
test 10
Output of Tester TorXakis instance:
TXS >> .....1: IN: Act { { ( In, [ -78 ] ) } }
TXS >> .....2: OUT: Act { { ( Out, [ -78 ] ) } }
TXS >> .....3: IN: Act { { ( In, [ -67 ] ) } }
TXS >> .....4: OUT: Act { { ( Out, [ -67 ] ) } }
TXS >> .....5: IN: Act { { ( In, [ -62 ] ) } }
TXS >> .....6: OUT: Act { { ( Out, [ -62 ] ) } }
TXS >> .....7: IN: Act { { ( In, [ -52 ] ) } }
TXS >> .....8: OUT: Act { { ( Out, [ -52 ] ) } }
TXS >> .....9: IN: Act { { ( In, [ -86 ] ) } }
TXS >> ....10: OUT: Act { { ( Out, [ -86 ] ) } }
TXS >> PASS
Output of Simulator TorXakis instance:
TXS >> .....1: OUT: No Output (Quiescence)
TXS >> .....2: OUT: No Output (Quiescence)
TXS >> .....3: IN: Act { { ( In, [ -78 ] ) } }
TXS >> .....4: OUT: Act { { ( Out, [ -78 ] ) } }
TXS >> .....5: OUT: No Output (Quiescence)
TXS >> .....6: IN: Act { { ( In, [ -67 ] ) } }
TXS >> .....7: OUT: Act { { ( Out, [ -67 ] ) } }
TXS >> .....8: OUT: No Output (Quiescence)
TXS >> .....9: IN: Act { { ( In, [ -62 ] ) } }
TXS >> ....10: OUT: Act { { ( Out, [ -62 ] ) } }
TXS >> ....11: IN: Act { { ( In, [ -52 ] ) } }
TXS >> ....12: OUT: Act { { ( Out, [ -52 ] ) } }
TXS >> ....13: IN: Act { { ( In, [ -86 ] ) } }
TXS >> ....14: OUT: Act { { ( Out, [ -86 ] ) } }
TXS >> ....15: OUT: No Output (Quiescence)
TXS >> ....16: OUT: No Output (Quiescence)
TXS >> ....17: OUT: No Output (Quiescence)
TXS >> ....18: OUT: No Output (Quiescence)
TXS >> ....19: OUT: No Output (Quiescence)
TXS >> ....20: OUT: No Output (Quiescence)
TXS >> PASS
How can we model shared memory, i.e., a global variable, in TorXakis?
For simplicity, we will assume that the shared memory stores a value of Data Type Int.
We define a process memory to manage the shared memory.
In the basic solution, this memory process has two communication channels of Data Type Int: Read and Write.
This memory process is a recursive process, with one parameter: the current memory value.
The process
either provides the current value over the Read channel,
or receives a new value over the Write channel.
Since reading a value from memory doesn’t change its value, after reading, the memory process is instantiated with the current memory value.
Since writing a value to memory changes its value, after writing, the memory process is instantiated with the new value.
PROCDEF memory [ Read, Write :: Int ] ( value :: Int ) ::=
Read ! value >-> memory [Read, Write]( value )
##
Write ? newValue >-> memory [Read, Write]( newValue )
ENDDEF
The memory process is used as follows, with initial value 0:
PROCDEF usage [ Read, Write :: Int ] ( ) ::=
memory [ Read, Write ] ( 0 )
|[ Read, Write ]|
someProcesses [ Read, Write ] ()
ENDDEF
where someProcesses contains read statements like
| `Read ? x` | _Read the value in memory_ |
|---|---|
| `Read ! 0` | _Read the memory when the value is zero_ |
| `Read ? x [[ x < 0 ]]` | _Read the memory when the value is less then zero_ |
and write statements like
| `Write ! 123` | _Write 123 to memory_ |
|---|---|
| `Write ? x` | _Write an arbritrary value to memory_ |
| `Write ? x [[ x > 123 ]]` | _Write a value larger than 123 to memory_ |
See the example ReadWriteConflict for more details.
In the advanced solution, the memory process has only one communication channel: Memory.
This communication channel has as Data Type MemoryAccess which is defined as follows
TYPEDEF MemoryAccess ::= Read { value :: Int }
| Write { newValue :: Int }
ENDDEF
The memory process is still a recursive process, with one parameter: the current memory value.
The process
either provides the Read constructor with the current value over the Memory channel,
or receives a Write constructor with the new value over the Memory channel.
Since reading a value from memory doesn’t change its value, after reading, the memory process is instantiated with the current memory value.
Since writing a value to memory changes its value, after writing, the memory process is instantiated with the new value.
PROCDEF memory [ Memory :: MemoryAccess ] ( value :: Int ) ::=
Memory ! Read ( value ) >-> memory [Memory](value)
##
Memory ? x [[ isWrite(x) ]] >-> memory [Memory](newValue(x))
ENDDEF
The memory process is used as follows, with initial value 0:
PROCDEF usage [ Memory :: MemoryAccess ] ( ) ::=
memory [ Memory ] ( 0 )
|[ Memory ]|
someProcesses [ Memory ] ()
ENDDEF
where someProcesses contains read statements like
| `Memory ? x [[ isRead(x) ]]` | _Read the value in memory_ |
|---|---|
| `Memory ! Read(0)` | _Read the memory when the value is zero_ |
| `Memory ? x [[ isRead(x) /\ (value(x) < 0) ]]` | _Read the memory when the value is less then zero_ |
and write statements like
| `Memory ! Write(123)` | _Write 123 to memory_ |
|---|---|
| `Memory ? x [[ isWrite(x) ]]` | _Write an arbritrary value to memory_ |
| `Memory ? x [[ isWrite(x) /\ (newValue(x) > 123) ]]` | _Write a value larger than 123 to memory_ |
The advanced solution has a better performance in TorXakis.
In this example, we model a control loop.
The control loop consists out of three processes: produce, measure, and correct.
Between these processes material and reports are exchanged.
The three processes repeat the following steps:
After briefly introducing the data types and function that are used in this model, we will discuss these three processes in order of simplicity. We will end with the complete control loop model.
All the files used in this example can be found at the example folder.
All data types are Cartesian Products of two integers: id and value.
TYPEDEF ProduceReport ::= ProduceReport { id, value :: Int } ENDDEF
TYPEDEF MeasureReport ::= MeasureReport { id, value :: Int } ENDDEF
TYPEDEF Correction ::= Correction { id, value :: Int } ENDDEF
Once we have the data types, channels needed for modelling this flow can be defined as:
CHANDEF Chans ::= In_Material :: Int
; Correction :: Correction
; ProduceReport :: ProduceReport
; Material :: Int
; MeasureReport :: MeasureReport
; Out_Material :: Int
ENDDEF
The sign function: zero for zero, +1 for all positive numbers, and -1 for all negative numbers.
FUNCDEF sgn ( x :: Int ) :: Int ::=
IF x > 0
THEN 1
ELSE IF x < 0
THEN -1
ELSE 0
FI
FI
ENDDEF
Correct is a repeating process of corrections.
All corrections need two inputs: a production report and a measurement report.
These reports must of course refer to the same material.
All corrections result in one output: a correction.
A correction contains
The correction value has a relation with the two inputs: the intended and measured values as reported in the production and measurement reports, respectively. This relation is expressed as a constraint between the correction, intended, and measured values.
The behaviour of the correct process is captured in the following recursive TorXakis Process Definition:
PROCDEF correct [ In_ProduceReport :: ProduceReport
; In_MeasureReport :: MeasureReport
; Out_Correction :: Correction
] ( ) ::=
In_ProduceReport ? pr | In_MeasureReport ? mr [[ id(pr) == id(mr) ]]
>-> Out_Correction ? correction [[ ( id(correction) == id(mr) ) /\ ( sgn(value(correction)) == sgn( value(pr) - value(mr) ) )]]
>-> correct [ In_ProduceReport, In_MeasureReport, Out_Correction ] ( )
ENDDEF
Measure is a repeating process of measurements.
All measurements need one input: the material to measure.
All measurements result in two outputs: the measured material and a report containing the measurement results.
The order of these two outputs is not constrained, i.e.,
Out_Material ||| Out_Report
Measure is modelled without buffers for material. So the behaviour of measure with respect to material is the alternating sequence of material coming in and material going out, i.e.,
In_Material >-> Out_Material >-> In_Material >-> Out_Material >-> In_Material >-> ...
Incoming material is associated with an identifier. This indentifier not only must be associated with the outgoing material but also be present in the generated report.
The behaviour of the measure process is captured in the following recursive TorXakis Process Definition:
PROCDEF measure [ In_Material :: Int
; Out_Report :: MeasureReport
; Out_Material :: Int
]( ) ::=
In_Material ? id
>-> (
Out_Report ? mr [[ id(mr) == id ]]
|||
(
Out_Material ! id
>-> measure [ In_Material, Out_Report, Out_Material ] ()
)
)
ENDDEF
Produce is a repeating process of production steps.
All production steps results in two outputs: material and report.
The order of these two outputs is not constrained, i.e.,
Out_Material ||| Out_Report
In the first production step, only material is needed as input.
In all other production steps, both material and correction are needed as inputs.
The order of these two inputs is not constrained, i.e.,
In_Material ||| In_Correction
All inputs are required to produce the output. So for all, but the first production step holds
( In_Material ||| In_Correction ) >>> ( Out_Material ||| Out_Report )
Produce is modelled without buffers for material. So the behaviour of produce with respect to material is the alternating sequence of material coming in and material going out, i.e.,
In_Material >-> Out_Material >-> In_Material >-> Out_Material >-> In_Material >-> ...
A correction is only obtained after both the production report and the outgoing material are used. To be precise, to obtain a correction both a production report and a measure report are needed. The latter is obtained when the material is measured. This requirement on order can be express as follows:
( Out_Material ||| Out_Report ) >>> In_Correction
Incoming material is associated with an identifier. This indentifier not only must be associated with the outgoing material but also be present in the generated report and in the resulting correction.
The behaviour of the produce process is captured in the following TorXakis Process Definitions.
These two processes were needed to capture the difference between the first and all other production steps.
PROCDEF produce [ In_Material :: Int
; In_Correction :: Correction
; Out_Material :: Int
; Out_ProduceReport :: ProduceReport
]( ) ::=
In_Material ? id
>-> produceLoop [In_Material, In_Correction, Out_Material, Out_ProduceReport] (id)
ENDDEF
PROCDEF produceLoop [ In_Material :: Int
; In_Correction :: Correction
; Out_Material :: Int
; Out_ProduceReport :: ProduceReport
]( id :: Int ) ::=
(
Out_Material ! id
>-> In_Material ? nextId
>-> EXIT ! nextId
)
|[ Out_Material ]|
(
(
( Out_Material ! id >-> EXIT )
|||
( Out_ProduceReport ? pr [[ id(pr) == id ]] >-> EXIT )
) >>>
( In_Correction ? correction [[ id (correction) == id ]] >-> EXIT ? nextId :: Int )
)
>>> ACCEPT ? nextId :: Int IN
produceLoop [In_Material, In_Correction, Out_Material, Out_ProduceReport] (nextId)
NI
ENDDEF
The behaviour of the control loop process is captured in the following TorXakis Process Definitions.
The three earlier described processes are linked together using their communication channels.
PROCDEF model [ In_Material :: Int
; Correction :: Correction
; ProduceReport :: ProduceReport
; Material :: Int
; MeasureReport :: MeasureReport
; Out_Material :: Int
]( ) ::=
(
produce [ In_Material, Correction, Material, ProduceReport ] ( )
|[ Material]|
measure [ Material, MeasureReport, Out_Material ] ( )
)
|[ ProduceReport, MeasureReport, Correction ]|
correct [ ProduceReport, MeasureReport, Correction ] ( )
ENDDEF
Since the above Control Loop process (model) puts everything together, now we can define our model as follows:
MODELDEF Model ::=
CHAN IN
CHAN OUT In_Material
, Correction
, ProduceReport
, Material
, MeasureReport
, Out_Material
SYNC {In_Material}
, {Correction}
, {ProduceReport}
, {Material}
, {MeasureReport}
, {Out_Material}
, {ProduceReport | MeasureReport}
BEHAVIOUR
model [In_Material, Correction, ProduceReport, Material, MeasureReport, Out_Material]()
ENDDEF
$> torxakis ControlLoopModel.txs
stepper Model
test 10
TorXakis will perform the actions at each step, as long as the Model behaves as expected or the number of steps are reached, then finally conclude:
TXS >> .....1: Act { { ( In_Material, [ 18 ] ) } }
TXS >> .....2: Act { { ( Material, [ 18 ] ) } }
TXS >> .....3: Act { { ( In_Material, [ -79 ] ) } }
TXS >> .....4: Act { { ( Out_Material, [ 18 ] ) } }
TXS >> .....5: Act { { ( MeasureReport, [ MeasureReport(18,-37) ] ) ( ProduceReport, [ ProduceReport(18,-73) ] ) } }
TXS >> .....6: Act { { ( Correction, [ Correction(18,-80) ] ) } }
TXS >> .....7: Act { { ( Material, [ -79 ] ) } }
TXS >> .....8: Act { { ( In_Material, [ -41 ] ) } }
TXS >> .....9: Act { { ( MeasureReport, [ MeasureReport(-79,-32) ] ) ( ProduceReport, [ ProduceReport(-79,-25) ] ) } }
TXS >> ....10: Act { { ( Out_Material, [ -79 ] ) } }
TXS >> PASS
Systems typically deal with large amounts of data. Data is often encoded in an Extensible Markup Language, which is defined in an XML Schema Definition.
This example is inspired by Microsoft’s sample XML File: Customers and Orders and associated Sample XSD File: Customers and Orders.
In the screenshot below, we see a folding editor in which one instance of each data type is unfolded.
All the files used in this example can be found at the example folder.
The system under test (SUT) communicates asynchronously.
The system under test has two input channels.
The system under test has one output channel.
On the output channel, the system will send a report that contains the received customers and orders so far (in xml).
After the initial report, a report will only be sent when additional input has been received.
A new report can incorporate multiple inputs, i.e., not every input necessarily results in an output.
The code for this SUT is implemented in this java file.
Using the sample XSD File: Customers and Orders, it is straightforward to define not only the following Type Definitions
TYPEDEF RootType ::=
C_RootType { customers :: List_CustomerType ; orders :: List_OrderType }
ENDDEF
TYPEDEF List_CustomerType ::=
CNil_CustomerType
| Cstr_CustomerType { head :: CustomerType; tail :: List_CustomerType }
ENDDEF
TYPEDEF List_OrderType ::=
CNil_OrderType
| Cstr_OrderType { head :: OrderType; tail :: List_OrderType }
ENDDEF
TYPEDEF CustomerType ::=
C_CustomerType { companyName :: String
; contactName :: String
; contactTitle :: String
; phone :: String
; fax :: Conditional_string
; fullAddress :: AddressType
; customerID :: Int }
ENDDEF
TYPEDEF AddressType ::=
C_AddressType { address :: String
; city :: String
; region :: String
; postalCode :: String
; country :: String }
ENDDEF
TYPEDEF OrderType ::=
C_OrderType { customerID :: Int
; employeeID :: Int
; orderDate :: Int
; requiredDate :: Int
; shipInfo :: ShipInfoType }
ENDDEF
TYPEDEF ShipInfoType ::=
C_ShipInfoType { shipVia :: Int
; freight :: Int
; shipName :: String
; shipAddress :: String
; shipCity :: String
; shipRegion :: String
; shipPostalCode :: String
; shipCountry :: String
; shippedDate :: Conditional_dateTime }
ENDDEF
but also the following Function Definitions to capture the constraints on these types:
FUNCDEF isValid_RootType ( t :: RootType ) :: Bool ::=
isValid_List_CustomerType(customers(t), 0, CAbsent_Int)
/\ isValid_List_OrderType(orders(t), 0, CAbsent_Int)
/\ uniqueCustomerIDs(customers(t))
/\ validCustomerIDsInOrders(orders(t),customers(t))
ENDDEF
FUNCDEF uniqueCustomerIDs ( x :: List_CustomerType ) :: Bool ::=
IF (isCNil_CustomerType (x))
THEN True
ELSE not(containsCustomerID(customerID(head (x)), tail(x))) /\ uniqueCustomerIDs(tail(x))
FI
ENDDEF
FUNCDEF containsCustomerID ( cid :: Int; x :: List_CustomerType ) :: Bool ::=
IF (isCNil_CustomerType (x))
THEN False
ELSE IF ( customerID(head (x)) == cid )
THEN True
ELSE containsCustomerID (cid, tail(x))
FI
FI
ENDDEF
FUNCDEF validCustomerIDsInOrders ( o :: List_OrderType; c :: List_CustomerType ) :: Bool ::=
IF (isCNil_OrderType (o))
THEN True
ELSE containsCustomerID(customerID(head(o)), c) /\ validCustomerIDsInOrders (tail(o), c)
FI
ENDDEF
FUNCDEF isValid_List_CustomerType ( x :: List_CustomerType; min :: Int; max :: Conditional_Int ) :: Bool ::=
isValidElementsList_CustomerType(x)
/\ (min <= lengthList_CustomerType(x))
/\ (IF isCPresent_Int(max) THEN lengthList_CustomerType(x) <= value(max) ELSE True FI)
ENDDEF
FUNCDEF isValidElementsList_CustomerType ( x :: List_CustomerType ) :: Bool ::=
IF isCstr_CustomerType(x)
THEN isValid_CustomerType(head(x)) /\ isValidElementsList_CustomerType(tail(x))
ELSE True
FI
ENDDEF
FUNCDEF lengthList_CustomerType ( x :: List_CustomerType ) :: Int ::=
IF isCNil_CustomerType(x) THEN 0 ELSE 1 + lengthList_CustomerType(tail(x)) FI
ENDDEF
FUNCDEF isValid_CustomerType ( t :: CustomerType ) :: Bool ::=
isValid_string(companyName(t))
/\ isValid_string(contactName(t))
/\ isValid_string(contactTitle(t))
/\ isValid_string(phone(t))
/\ isValid_Conditional_string(fax(t))
/\ isValid_AddressType(fullAddress(t))
/\ isValid_unsignedLong(customerID(t))
ENDDEF
FUNCDEF isValid_AddressType ( t :: AddressType ) :: Bool ::=
isValid_string(address(t))
/\ isValid_string(city(t))
/\ isValid_string(region(t))
/\ isValid_string(postalCode(t))
/\ isValid_string(country(t))
ENDDEF
FUNCDEF isValid_List_OrderType ( x :: List_OrderType; min :: Int; max :: Conditional_Int ) :: Bool ::=
isValidElementsList_OrderType(x)
/\ (min <= lengthList_OrderType(x))
/\ (IF isCPresent_Int(max) THEN lengthList_OrderType(x) <= value(max) ELSE True FI)
ENDDEF
FUNCDEF isValidElementsList_OrderType ( x :: List_OrderType ) :: Bool ::=
IF isCstr_OrderType(x) THEN isValid_OrderType(head(x)) /\ isValidElementsList_OrderType(tail(x)) ELSE True FI
ENDDEF
FUNCDEF lengthList_OrderType ( x :: List_OrderType ) :: Int ::=
IF isCNil_OrderType(x) THEN 0 ELSE 1 + lengthList_OrderType(tail(x)) FI
ENDDEF
FUNCDEF isValid_OrderType ( t :: OrderType ) :: Bool ::=
isValid_unsignedLong(customerID(t))
/\ isValid_unsignedInt(employeeID(t))
/\ isValid_dateTime(orderDate(t))
/\ isValid_dateTime(requiredDate(t))
/\ isValid_ShipInfoType(shipInfo(t))
/\ (requiredDate(t) > orderDate(t))
/\ ( LET sd = shippedDate(shipInfo(t)) IN IF isCPresent_dateTime(sd) THEN value(sd) >= orderDate(t) ELSE True FI NI )
ENDDEF
FUNCDEF isValid_ShipInfoType ( t :: ShipInfoType ) :: Bool ::=
isValid_integer(shipVia(t))
/\ isValid_decimal(freight(t))
/\ isValid_string(shipName(t))
/\ isValid_string(shipAddress(t))
/\ isValid_string(shipCity(t))
/\ isValid_string(shipRegion(t))
/\ isValid_string(shipPostalCode(t))
/\ isValid_string(shipCountry(t))
/\ isValid_Conditional_dateTime(shippedDate(t))
ENDDEF
Since TorXakis assumes synchronous communication, yet the system under test communicates
asynchronously, we have to include the asynchronous communication channel as well.
TYPEDEF StringList ::= Nil
| Cons { hd :: String
; tl :: StringList
}
ENDDEF
FUNCDEF add ( x :: String; l :: StringList ) :: StringList
::= IF isNil(l)
THEN Cons(x,Nil)
ELSE Cons(hd(l),add(x,tl(l)))
FI
ENDDEF
PROCDEF bufferedOutput [ IReport, OReport :: String ] (queue :: StringList) ::=
IReport ? r >-> bufferedOutput [ IReport, OReport ] (add (r , queue))
##
[[ isCons (queue) ]] =>> OReport ! hd(queue) >-> bufferedOutput [ IReport, OReport ] (tl(queue))
ENDDEF
Using these Type Definitions and Function Definitions we define the following Process Definition,
Channel Definition, Model Definition, and Connection Definition:
PROCDEF handle [ Customer :: CustomerType; Order :: OrderType; Report :: String ] (cs :: List_CustomerType; os :: List_OrderType; changed :: Bool) EXIT ::=
[[ changed ]] =>> ( Report ! toXml ( C_RootType ( cs, os ) )
>-> handle [Customer , Order , Report ] ( cs , os , False)
)
##
( Customer ? c [[ isValid_CustomerType(c) /\ not ( containsCustomerID ( customerID ( c ) , cs ) ) ]]
>-> handle [Customer, Order, Report] ( Cstr_CustomerType ( c, cs ), os , True )
)
##
( [[ isCstr_CustomerType(cs) ]] =>> Order ? o [[ isValid_OrderType(o) /\ containsCustomerID ( customerID(o), cs ) ]]
>-> handle [Customer, Order, Report] ( cs, Cstr_OrderType ( o, os ) , True )
)
ENDDEF
CHANDEF Chans ::= Customer :: CustomerType
; Order :: OrderType
; Report :: String
ENDDEF
MODELDEF Model ::=
CHAN IN Customer, Order
CHAN OUT Report
BEHAVIOUR
HIDE [ HReport :: String ] IN
handle [ Customer, Order, HReport ] ( CNil_CustomerType, CNil_OrderType, True )
|[ HReport ]|
bufferedOutput [ HReport, Report ] (Nil)
NI
ENDDEF
CNECTDEF Sut
::=
CLIENTSOCK
CHAN OUT Customer HOST "localhost" PORT 7890
ENCODE Customer ? c -> ! toXml(c)
CHAN OUT Order HOST "localhost" PORT 7891
ENCODE Order ? o -> ! toXml(o)
CHAN IN Report HOST "localhost" PORT 7892
DECODE Report ! s <- ? s
ENDDEF
where the toXml functions are defined as follows
FUNCDEF toXml (r :: RootType) :: String ::=
"<Root>" ++
"<Customers>" ++
toXml (customers(r)) ++
"</Customers>" ++
"<Orders>" ++
toXml (orders(r)) ++
"</Orders>" ++
"</Root>"
ENDDEF
FUNCDEF toXml (lc :: List_CustomerType) :: String ::=
IF isCNil_CustomerType(lc)
THEN ""
ELSE toXml(head(lc)) ++ toXml(tail(lc))
FI
ENDDEF
FUNCDEF toXml (lo :: List_OrderType) :: String ::=
IF isCNil_OrderType(lo)
THEN ""
ELSE toXml(head(lo)) ++ toXml(tail(lo))
FI
ENDDEF
FUNCDEF toXml (c :: CustomerType) :: String ::=
"<Customer CustomerID=" ++ toString(customerID(c)) ++ ">" ++
"<CompanyName>"++ companyName(c) ++ "</CompanyName>"++
"<ContactName>" ++ contactName(c) ++ "</ContactName>" ++
"<ContactTitle>" ++ contactTitle(c) ++ "</ContactTitle>" ++
"<Phone>" ++ phone(c) ++ "</Phone>" ++
( IF isCPresent_string(fax(c)) THEN
"<Fax>" ++ value(fax(c)) ++ "</Fax>"
ELSE
""
FI
) ++
toXml(fullAddress(c)) ++
"</Customer>"
ENDDEF
FUNCDEF toXml (o :: OrderType) :: String ::=
"<Order>" ++
"<CustomerID>" ++ toString(customerID(o)) ++ "</CustomerID>" ++
"<EmployeeID>" ++ toString(employeeID(o)) ++ "</EmployeeID>" ++
"<OrderDate>" ++ toString(orderDate(o)) ++ "</OrderDate>" ++
"<RequiredDate>" ++ toString(requiredDate(o)) ++ "</RequiredDate>" ++
toXml(shipInfo(o)) ++
"</Order>"
ENDDEF
FUNCDEF toXml (a :: AddressType) :: String ::=
"<FullAddress>" ++
"<Address>" ++ address(a) ++ "</Address>" ++
"<City>" ++ city(a) ++ "</City>" ++
"<Region>" ++ region(a) ++ "</Region>" ++
"<PostalCode>" ++ postalCode(a) ++ "</PostalCode>" ++
"<Country>" ++ country(a) ++ "</Country>" ++
"</FullAddress>"
ENDDEF
FUNCDEF toXml (s :: ShipInfoType) :: String ::=
"<ShipInfo"++
( IF isCPresent_dateTime(shippedDate(s)) THEN
" ShippedDate=" ++ toString(value(shippedDate(s))) ++ ">"
ELSE
">"
FI
) ++
"<ShipVia>" ++ toString(shipVia(s)) ++ "</ShipVia>" ++
"<Freight>" ++ toString(freight(s)) ++ "</Freight>" ++
"<ShipName>" ++ shipName(s) ++ "</ShipName>" ++
"<ShipAddress>" ++ shipAddress(s) ++ "</ShipAddress>" ++
"<ShipCity>" ++ shipCity(s) ++ "</ShipCity>" ++
"<ShipRegion>" ++ shipRegion(s) ++ "</ShipRegion>" ++
"<ShipPostalCode>" ++ shipPostalCode(s) ++ "</ShipPostalCode>" ++
"<ShipCountry>" ++ shipCountry(s) ++ "</ShipCountry>" ++
"</ShipInfo>"
ENDDEF
$> java CustomersOrders
$> torxakis CustomersOrders.txs
tester Model Sut
test 10
TorXakis will perform an Order, Report or Customer action with various parameters at each step, as long as the SUT responds as expected or the number of test steps are reached, then finally conclude:
TXS >> .....1: OUT: Act { { ( Report, [ Report(Nil_Customer,Nil_Order) ] ) } }
TXS >> .....2: IN: Act { { ( Order, [ Order(49,6,-99,-21,ShipInfo(-52,-41,"A","P","PPAAA","U","K","",Absent_dateTime)) ] ) } }
TXS >> .....3: OUT: Act { { ( Report, [ Report(Nil_Customer,Cstr_Order(Order(49,6,-99,-21,ShipInfo(-52,-41,"A","P","PPAAA","U","K","",Absent_dateTime)),Nil_Order)) ] ) } }
TXS >> .....4: IN: Act { { ( Order, [ Order(49,15,-75,35,ShipInfo(46,-55,"A","","AT","PBY","","B",Present_dateTime(-4))) ] ) } }
TXS >> .....5: OUT: Act { { ( Report, [ Report(Nil_Customer,Cstr_Order(Order(49,15,-75,35,ShipInfo(46,-55,"A","","AT","PBY","","B",Present_dateTime(-4))),Cstr_Order(Order(49,6,-99,-21,ShipInfo(-52,-41,"A","P","PPAAA","U","K","",Absent_dateTime)),Nil_Order))) ] ) } }
TXS >> .....6: IN: Act { { ( Order, [ Order(49,16,-100,-97,ShipInfo(-98,-63,"","","Q","P","D","X",Absent_dateTime)) ] ) } }
TXS >> .....7: OUT: Act { { ( Report, [ Report(Nil_Customer,Cstr_Order(Order(49,16,-100,-97,ShipInfo(-98,-63,"","","Q","P","D","X",Absent_dateTime)),Cstr_Order(Order(49,15,-75,35,ShipInfo(46,-55,"A","","AT","PBY","","B",Present_dateTime(-4))),Cstr_Order(Order(49,6,-99,-21,ShipInfo(-52,-41,"A","P","PPAAA","U","K","",Absent_dateTime)),Nil_Order)))) ] ) } }
TXS >> .....8: IN: Act { { ( Order, [ Order(49,40,-65,77,ShipInfo(-28,-37,"X","D","B","B","","",Present_dateTime(-58))) ] ) } }
TXS >> .....9: OUT: Act { { ( Report, [ Report(Nil_Customer,Cstr_Order(Order(49,40,-65,77,ShipInfo(-28,-37,"X","D","B","B","","",Present_dateTime(-58))),Cstr_Order(Order(49,16,-100,-97,ShipInfo(-98,-63,"","","Q","P","D","X",Absent_dateTime)),Cstr_Order(Order(49,15,-75,35,ShipInfo(46,-55,"A","","AT","PBY","","B",Present_dateTime(-4))),Cstr_Order(Order(49,6,-99,-21,ShipInfo(-52,-41,"A","P","PPAAA","U","K","",Absent_dateTime)),Nil_Order))))) ] ) } }
TXS >> ....10: IN: Act { { ( Customer, [ Customer("P","H","","C",Absent_string,Address("X","P","A","BAD",""),90) ] ) } }
TXS >> PASS
Your assignment is to test the Lucky People program with TorXakis.
The Lucky People program gets as input a sequence of persons on socket 7777.
A person has a sex, first name, last name, day and month of birth.
For each person, the Lucky People program produces one output, a string on socket 7777.
The string is either True or False, and reflects whether the person is considered lucky.
A person is lucky based on
The input sequence is specified as follows:
| Specification | Structure | Constraints |
|---|---|---|
| persons | (person ‘\n’)* | |
| person | sex separator firstName separator lastName separator dayOfBirth separator monthOfBirth | |
| separator | ‘@’ | |
| sex | ‘Male’|‘Female’ | |
| firstName | name | |
| lastName | name | |
| name | [A-Z][a-z]* | |
| dayOfBirth | Int | 1 <= dayOfBirth <= 31 |
| monthOfBirth | Int | 1 <= monthOfBirth <= 12 |
In the following sequences of persons, the persons in italics are considered lucky due to their position in the sequence
Male@Huey@Duck@17@10
Male@Dewey@Duck@17@10
Male@Louie@Duck@17@10
Male@Mickey@Mouse@13@1
Male@Donald@Duck@13@3
Female@April@Duck@15@5
Female@Beatrix@Oranje@31@1
Female@Maxima@Zorreguieta@17@5
Female@Amalia@Oranje@7@12
Female@Alexia@Oranje@26@6
Female@Ariane@Oranje@10@4
Male@Willem@Oranje@27@4
Provide a TorXakis model: a file named ‘LuckyPeople.txs’ containing a model definition and connection definition.
Provide a test report: a file containing the verdict whether ‘LuckyPeople.java’ satisfies the requirements and the actual trace(s) used to test the program.
We want to test our java program LuckyPeople.java.
This program gets as input a sequence of persons and determines if those people are lucky. The detailed behaviour of this program can be found at the assignment page.
All the files used in this example can be found at the example folder.
We start with defining the types that are needed to model This program’s (our System Under Test - SUT) behaviour.
The input of our SUT are persons with first name, last name, sex, day of birth and month of birth.  Let’s define the channels needed for modelling this behaviour:
CHANDEF Channels ::= In :: Person
; Out :: Bool
ENDDEF
In our model definition, we need a way to define the behaviour of determining whether a Person is lucky or not.
Let’s implement a procedure definition for this:
PROCDEF luckyPeople [ In :: Person; Out :: Bool ] ( last :: Sex; n :: Int ) ::=
“In” and “Out” are our channels, while “last” and “n” are the parameters of this procedure. We added the parameters because we want to keep track of how many people of the same sex have been before current person, since it is one of the ways of determining whether a person is lucky.
We want to test our SUT with inputs that make sense, so we should tell TorXakis what makes a Person input valid. Let’s add a function as a constraint for the input:
In ? p [[ isValid_Person(p) ]]
We’re going to implement “isValid_Person()” function later. For now let’s focus on the process.
Next, we want to communicate to the output whether this person is lucky or not. Let’s use another function for it:
>-> Out ! isLuckyPerson (p, last, n)
“>->” is the Sequence Operator. It means that after the process on the left has communicated, the described process behaviour on the right is exposed.
After communicating the result to the output channel, it’s time to go back and wait for next input. There’s one catch, though: As we said above, we should keep track of how many people with the current sex have been processed so far.
>->(
( [[ sex(p) == last ]] =>> luckyPeople[In,Out] ( sex(p), n+1 ) )
##
( [[ sex(p) <> last ]] =>> luckyPeople[In,Out] ( sex(p), 1 ) )
)
“##” is the Choice Operator. It means that either one of those processes are executed, but never both.
“=>>” is the Guard Operator. The process behaviour on the right is executed only if the expression on the left of it is true.
So the process definition of Lucky People looks like this:
PROCDEF luckyPeople [ In :: Person; Out :: Bool ] ( last :: Sex; n :: Int ) ::=
In ? p [[ isValid_Person(p) ]]
>-> Out ! isLuckyPerson (p, last, n)
>->(
( [[ sex(p) == last ]] =>> luckyPeople[In,Out] ( sex(p), n+1 ) )
##
( [[ sex(p) <> last ]] =>> luckyPeople[In,Out] ( sex(p), 1 ) )
)
ENDDEF
Now we can use this procedure definition in our Model.
The model should specify that the system uses two channels, one incoming for the Person and one outgoing for the result.
It should also specify that “luckyPeople” process is executed with the input and this process’s output is communicated to the out channel as this model’s behaviour.
MODELDEF Model ::=
CHAN IN In
CHAN OUT Out
BEHAVIOUR
luckyPeople[In, Out](Male,0) -- first sex choice is arbitrary
ENDDEF
We’re not done yet. We need to implement the function definitions that our “luckyPeople” process uses.
We want to validate the input in order to make sure that it represents data of a person that can actually exist.
FUNCDEF isValid_Person (p :: Person) :: Bool ::=
strinre (firstName(p), REGEX ('[A-Z][a-z]*'))
/\ strinre (lastName(p), REGEX ('[A-Z][a-z]*'))
/\ (1 <= dayOfBirth(p)) /\ (dayOfBirth(p) <= 31)
/\ (1 <= monthOfBirth(p)) /\ (monthOfBirth(p) <= 12)
ENDDEF
“strinre” function checks whether the given string matches the given Regular Expression. First two lines ensure that only the inputs with Capital case first name and surname are valid.
To make the “luckyPerson” process cleaner, we decided to extract the logic of determining the person’s luckiness into a separate function. As we have seen in the assignment page, a person can be lucky based on 3 criteria: gender, name or birthday. So our function definition should be something like this:
FUNCDEF isLuckyPerson (p :: Person; last :: Sex; n :: Int) :: Bool ::=
isLuckyByGender(p, last, n)
\/ isLuckyByName(p)
\/ isLuckyByBirthday(p)
ENDDEF
Now let’s define each of these criteria as separate function definitions.
A person is lucky by gender if previous 5 people were all from the opposite sex.
FUNCDEF isLuckyByGender (p :: Person; last :: Sex; n :: Int) :: Bool ::=
( sex(p) <> last ) /\ ( n >= 5 )
ENDDEF
A person is lucky by name if both it’s name and surname start with the same letter.
FUNCDEF isLuckyByName (p :: Person) :: Bool ::=
at(firstName(p), 0 ) == at(lastName(p), 0 )
ENDDEF
A person is lucky by birthday if both day and month of it’s birthday are the same.
FUNCDEF isLuckyByBirthday (p :: Person) :: Bool ::=
dayOfBirth(p) == monthOfBirth(p)
ENDDEF
Our SUT communicates with the outside world by sending and receiving lines i.e. strings terminated by a line feed, over a socket at port 7777.
The SUT also expects one person per input line, fields separated by “@” sign. So we should make sure that the Person type in our TorXakis model is properly serialized before being communicated to the SUT. The return value from the SUT should also be deserialized into proper data structure (Bool).
Assuming that TorXakis and the SUT run on the same machine (localhost) the SUT connection can be defined in TorXakis as follows:
CONSTDEF separator :: String ::= "@" ENDDEF
CNECTDEF Sut ::=
CLIENTSOCK
CHAN OUT In HOST "localhost" PORT 7777
ENCODE In ? p -> ! toString(sex(p)) ++ separator ++
firstName(p) ++ separator ++
lastName(p) ++ separator ++
toString(dayOfBirth(p)) ++ separator ++
toString(monthOfBirth(p))
CHAN IN Out HOST "localhost" PORT 7777
DECODE Out ! fromString(s) <- ? s
ENDDEF
$> java LuckyPeople
$> torxakis LuckyPeople.txs
tester Model Sut
test 50
TorXakis will create valid random Person data, pass it to SUT and receive the output at each step, as long as the SUT responds as expected or the number of test steps are reached, then finally conclude:
TXS >> .....1: IN: Act { { ( In, [ Person(Male,"W","Phz",22,9) ] ) } }
TXS >> .....2: OUT: Act { { ( Out, [ False ] ) } }
TXS >> .....3: IN: Act { { ( In, [ Person(Male,"Pa","Hrd",2,2) ] ) } }
TXS >> .....4: OUT: Act { { ( Out, [ True ] ) } }
...
TXS >> ....47: IN: Act { { ( In, [ Person(Female,"Pk","Pq",3,11) ] ) } }
TXS >> ....48: OUT: Act { { ( Out, [ True ] ) } }
TXS >> ....49: IN: Act { { ( In, [ Person(Female,"Pp","La",31,1) ] ) } }
TXS >> ....50: OUT: Act { { ( Out, [ False ] ) } }
TXS >> PASS
TorXakis is capable of XML-based communication with SUT’s. We don’t have an SUT which does that but TorXakis can help us there, too: TorXakis can also act as a simulator which behaves based on a model.
Let’s define another connection and a simulator, both of which use XML-based communication.
CNECTDEF Xut ::=
CLIENTSOCK
CHAN OUT In HOST "localhost" PORT 7777
ENCODE In ? p -> ! toXml(p)
CHAN IN Out HOST "localhost" PORT 7777
DECODE Out ! fromXml(s) <- ? s
ENDDEF
CNECTDEF Xim ::=
SERVERSOCK
CHAN IN In HOST "localhost" PORT 7777
DECODE In ! fromXml(s) <- ? s
CHAN OUT Out HOST "localhost" PORT 7777
ENCODE Out ? b -> ! toXml(b)
ENDDEF
Let’s test our simulator.
$> torxakis LuckyPeople.txs
simulator Model Xim
TorXakis will hang, waiting for a tester to connect.
$> torxakis LuckyPeople.txs
tester Model Xut
As soon as you enter this command, you’ll see that Simulator also responds:
TXS >> Simulator started
param param_Sim_deltaTime 4000
param param_Sut_deltaTime 4000
sim 30
test 10
Now you’ll see the tester TorXakis instance happily testing the simulator:
TXS >> .....1: IN: Act { { ( In, [ Person(Male,"K","D",2,1) ] ) } }
TXS >> .....2: OUT: Act { { ( Out, [ False ] ) } }
TXS >> .....3: IN: Act { { ( In, [ Person(Male,"B","L",8,12) ] ) } }
TXS >> .....4: OUT: Act { { ( Out, [ False ] ) } }
TXS >> .....5: IN: Act { { ( In, [ Person(Male,"Phdppab","S",19,2) ] ) } }
TXS >> .....6: OUT: Act { { ( Out, [ False ] ) } }
TXS >> .....7: IN: Act { { ( In, [ Person(Male,"Addp","Pz",17,8) ] ) } }
TXS >> .....8: OUT: Act { { ( Out, [ False ] ) } }
TXS >> .....9: IN: Act { { ( In, [ Person(Female,"Hfhnad","Ln",4,8) ] ) } }
TXS >> ....10: OUT: Act { { ( Out, [ True ] ) } }
TXS >> PASS
And simulator TorXakis instance acting as the SUT:
TXS >> .....1: OUT: No Output (Quiescence)
TXS >> .....2: OUT: No Output (Quiescence)
TXS >> .....3: IN: Act { { ( In, [ Person(Male,"K","D",2,1) ] ) } }
TXS >> .....4: OUT: Act { { ( Out, [ False ] ) } }
TXS >> .....5: OUT: No Output (Quiescence)
TXS >> .....6: IN: Act { { ( In, [ Person(Male,"B","L",8,12) ] ) } }
TXS >> .....7: OUT: Act { { ( Out, [ False ] ) } }
TXS >> .....8: IN: Act { { ( In, [ Person(Male,"Phdppab","S",19,2) ] ) } }
TXS >> .....9: OUT: Act { { ( Out, [ False ] ) } }
TXS >> ....10: OUT: No Output (Quiescence)
TXS >> ....11: IN: Act { { ( In, [ Person(Male,"Addp","Pz",17,8) ] ) } }
TXS >> ....12: OUT: Act { { ( Out, [ False ] ) } }
TXS >> ....13: IN: Act { { ( In, [ Person(Female,"Hfhnad","Ln",4,8) ] ) } }
TXS >> ....14: OUT: Act { { ( Out, [ True ] ) } }
TXS >> ....15: OUT: No Output (Quiescence)
...
TXS >> ....30: OUT: No Output (Quiescence)
TXS >> PASS
We can also tell TorXakis to use predetermined input data for testing. For this, we can make use of Test Purposes. We’ll define a process that communicates Person data and resulting boolean at each step, then we’ll add as many steps as we want for our predetermined input, and then we’ll use this process in our Test Purpose.
Let’s create a PurposeExamples.txs file and define that process and write some test data with expected results:
PROCDEF examples [ In :: Person; Out :: Bool ] () HIT ::=
In ! Person( Male, "Mickey", "Mouse", 13, 1 )
>-> Out ! True
>-> In ! Person( Male, "Donald", "Duck", 13, 3 )
>-> Out ! True
>-> In ! Person( Male, "Luuk", "Laar", 24, 12 )
>-> Out ! True
>-> In ! Person( Female, "Shakira", "Ripoll", 2, 2 )
>-> Out ! True
>-> In ! Person( Male, "Michael", "Buble", 9, 9 )
>-> Out ! True
>-> In ! Person( Female, "Imke", "Laar", 7, 7 )
>-> Out ! True
>-> In ! Person( Male, "Huey", "Duck", 17, 10 )
>-> Out ! False
>-> In ! Person( Male, "Dewey", "Duck", 17, 10 )
>-> Out ! True
>-> In ! Person( Male, "Louie", "Duck", 17, 10 )
>-> Out ! False
>-> In ! Person( Male, "Mickey", "Mouse", 13, 1 )
>-> Out ! True
>-> In ! Person( Male, "Donald", "Duck", 13, 3 )
>-> Out ! True
>-> In ! Person( Female, "April", "Duck", 15, 5 )
>-> Out ! True
>-> In ! Person( Female, "Beatrix", "Oranje", 31, 1 )
>-> Out ! False
>-> In ! Person( Female, "Maxima", "Zorreguieta", 17, 5 )
>-> Out ! False
>-> In ! Person( Female, "Amalia", "Oranje", 7, 12 )
>-> Out ! False
>-> In ! Person( Female, "Alexia", "Oranje", 26, 6 )
>-> Out ! False
>-> In ! Person( Female, "Ariane", "Oranje", 10, 4 )
>-> Out ! False
>-> In ! Person( Male, "Willem", "Oranje", 27, 4 )
>-> Out ! True
ENDDEF
Mind the HIT keyword on first line. This keyword is necessary in order to use it as a Goal in the Test Purpose definition below.
Now we should make sure the generated input for our SUT is synchronized with what this process communicates to the channels. Let’s define the Test Purpose for this:
PURPDEF PurposeExamples ::=
CHAN IN In
CHAN OUT Out
GOAL examples ::= examples [In,Out] ()
ENDDEF
Defining the Goal of the Test Purpose with examples process effectively forces the Persons in examples process to be communicated through In channel to SUT and expects the output in Out channel to match whatever is defined in examples process.
Now we can use this Test Purpose to test SUT with our predetermined inputs.
$> java LuckyPeople
$> torxakis LuckyPeople.txs PurposeExamples.txs
tester Model PurposeExamples Sut
test 50
TXS >> .....1: IN: Act { { ( In, [ Person(Male,"Mickey","Mouse",13,1) ] ) } }
TXS >> .....2: OUT: Act { { ( Out, [ True ] ) } }
TXS >> .....3: OUT: No Output (Quiescence)
TXS >> .....4: IN: Act { { ( In, [ Person(Male,"Donald","Duck",13,3) ] ) } }
TXS >> .....5: OUT: Act { { ( Out, [ True ] ) } }
TXS >> .....6: OUT: No Output (Quiescence)
TXS >> .....7: IN: Act { { ( In, [ Person(Male,"Luuk","Laar",24,12) ] ) } }
TXS >> .....8: OUT: Act { { ( Out, [ True ] ) } }
TXS >> .....9: OUT: No Output (Quiescence)
TXS >> ....10: IN: Act { { ( In, [ Person(Female,"Shakira","Ripoll",2,2) ] ) } }
TXS >> ....11: OUT: Act { { ( Out, [ True ] ) } }
TXS >> ....12: OUT: No Output (Quiescence)
TXS >> ....13: IN: Act { { ( In, [ Person(Male,"Michael","Buble",9,9) ] ) } }
TXS >> ....14: OUT: Act { { ( Out, [ True ] ) } }
TXS >> ....15: IN: Act { { ( In, [ Person(Female,"Imke","Laar",7,7) ] ) } }
TXS >> ....16: OUT: Act { { ( Out, [ True ] ) } }
TXS >> ....17: OUT: No Output (Quiescence)
TXS >> ....18: IN: Act { { ( In, [ Person(Male,"Huey","Duck",17,10) ] ) } }
TXS >> ....19: OUT: Act { { ( Out, [ False ] ) } }
TXS >> ....20: OUT: No Output (Quiescence)
TXS >> ....21: IN: Act { { ( In, [ Person(Male,"Dewey","Duck",17,10) ] ) } }
TXS >> ....22: OUT: Act { { ( Out, [ True ] ) } }
TXS >> ....23: IN: Act { { ( In, [ Person(Male,"Louie","Duck",17,10) ] ) } }
TXS >> ....24: OUT: Act { { ( Out, [ False ] ) } }
TXS >> ....25: OUT: No Output (Quiescence)
TXS >> ....26: IN: Act { { ( In, [ Person(Male,"Mickey","Mouse",13,1) ] ) } }
TXS >> ....27: OUT: Act { { ( Out, [ True ] ) } }
TXS >> ....28: OUT: No Output (Quiescence)
TXS >> ....29: IN: Act { { ( In, [ Person(Male,"Donald","Duck",13,3) ] ) } }
TXS >> ....30: OUT: Act { { ( Out, [ True ] ) } }
TXS >> ....31: IN: Act { { ( In, [ Person(Female,"April","Duck",15,5) ] ) } }
TXS >> ....32: OUT: Act { { ( Out, [ True ] ) } }
TXS >> ....33: IN: Act { { ( In, [ Person(Female,"Beatrix","Oranje",31,1) ] ) } }
TXS >> ....34: OUT: Act { { ( Out, [ False ] ) } }
TXS >> ....35: OUT: No Output (Quiescence)
TXS >> ....36: IN: Act { { ( In, [ Person(Female,"Maxima","Zorreguieta",17,5) ] ) } }
TXS >> ....37: OUT: Act { { ( Out, [ False ] ) } }
TXS >> ....38: OUT: No Output (Quiescence)
TXS >> ....39: IN: Act { { ( In, [ Person(Female,"Amalia","Oranje",7,12) ] ) } }
TXS >> ....40: OUT: Act { { ( Out, [ False ] ) } }
TXS >> ....41: OUT: No Output (Quiescence)
TXS >> ....42: IN: Act { { ( In, [ Person(Female,"Alexia","Oranje",26,6) ] ) } }
TXS >> ....43: OUT: Act { { ( Out, [ False ] ) } }
TXS >> ....44: IN: Act { { ( In, [ Person(Female,"Ariane","Oranje",10,4) ] ) } }
TXS >> ....45: OUT: Act { { ( Out, [ False ] ) } }
TXS >> ....46: IN: Act { { ( In, [ Person(Male,"Willem","Oranje",27,4) ] ) } }
TXS >> ....47: OUT: Act { { ( Out, [ True ] ) } }
TXS >> ....48: OUT: No Output (Quiescence)
TXS >> Goal examples: Hit
TXS >> PASS
One of the situations that makes a person lucky is when that person’s sex is different from previous 5 people. Even though our predetermined inputs cover this case, this criteria comes with implied conditions that:
Covering every possible case that is implied by above conditions by using predetermined input is not only not practical but also defeats the purpose of using TorXakis for Model Based Testing. We should make TorXakis test these situations while still generating test data randomly. We can do it by using a Test Purpose that only enforces the sex of generated Person data and leaves the rest to be generated by TorXakis.
Let’s create a PurposeLuckyByGender.txs file and define the process and the Test Purpose in it.
Here is such a Process Definition that can be used for this purpose:
PROCDEF repeatAndSwitchGender [ In :: Person ; Out :: Bool ] ( pos, length :: Int; s :: Sex) HIT ::=
(
[[ pos > 1 ]] =>> In ? p [[ sex(p) == s ]] >-> EXIT
##
[[ pos == 1 ]] =>> In ? p [[ (sex(p) == s)
/\ ( not (isLuckyByName(p)))
/\ ( not (isLuckyByBirthday(p)))
]] >-> EXIT
)
>>> Out ? b
>-> (
[[pos == length ]] =>> (
[[ isMale(s) ]] =>> repeatAndSwitchGender [In,Out] (1, length, Female)
##
[[ isFemale(s) ]] =>> repeatAndSwitchGender [In,Out] (1, length+1, Male)
)
##
[[pos < length ]] =>> repeatAndSwitchGender [In, Out] (pos+1,length, s)
)
ENDDEF
Let’s walk through this Process Definition step by step.
First block in paranthesis **(...)**
enforces the criteria on the person data that is communicated through In channel:
(
[[ pos > 1 ]] =>> In ? p [[ sex(p) == s ]] >-> EXIT
##
[[ pos == 1 ]] =>> In ? p [[ (sex(p) == s)
/\ ( not (isLuckyByName(p)))
/\ ( not (isLuckyByBirthday(p)))
]] >-> EXIT
)
If current person is not the first person of current gender (position counter is greater than 1) then we just enforce that its gender is the sex that is passed in as parameter.
If current person is the first person of current gender (position counter is 1) then we enforce not only that its gender is the sex that is passed in as parameter, but also that this person is not lucky based on other criteria. Because, with this purpose, we want to observe whether the current person is going to be deemed lucky based on the number of people who came before consecutively with opposite sex. E.g. if a Female comes after 6 consecutive Males and is evaluated to be lucky, we want to be sure that it is because of her gender and not her name or birthday.
“##” is the Choice Operator. It means that either one of those processes are executed, but never both.
“EXIT” keywords at the end of both processes are needed to signal exiting the block defined in paranthesis.
>>> Out ? b
This line just reads from the Out channel into b variable. This variable is not going to be used, but it has to be defined since the Test Purpose has to define what should be done with all the channels.
“>>>” is the Enable Operator. It means that the flow synchronizes on EXIT of multiple processes. Here it signals the continuation after exiting the previous block.
Next block in paranthesis “()” enforces repeating the same sex for a number of times, for both sexes, then increments the repetition number and repeats:
(
[[pos == length ]] =>> (
[[ isMale(s) ]] =>> repeatAndSwitchGender [In,Out] (1, length, Female)
##
[[ isFemale(s) ]] =>> repeatAndSwitchGender [In,Out] (1, length+1, Male)
)
##
[[pos < length ]] =>> repeatAndSwitchGender [In, Out] (pos+1,length, s)
)
If current position counter (pos) reached the requested length, then switch the genders. We start with Males, so after having requested number (length) of Males in a row, it’s time to request the same number of Females. After having the same number of Females, switch back to Males and increment the requested length.
If current position counter (pos) is still below the requested length, then just increment the position counter and request another person of the same sex with previous person.
There’s no upper limit defined for the repetition number (length), so as long as we run TorXakis the generated persons’ genders will be like this: MFMMFFMMMFFFMMMMFFFF…
Let’s write a Test Purpose that uses repeatAndSwitchGender process to manipulate test data generated by TorXakis:
PURPDEF PurposeLuckyByGender ::=
CHAN IN In
CHAN OUT Out
GOAL luckyByGender ::= repeatAndSwitchGender [In,Out] (1,1,Male)
ENDDEF
Now we can use this Test Purpose to test SUT for various “Lucky by gender” cases.
$> java LuckyPeople
$> torxakis LuckyPeople.txs PurposeLuckyByGender.txs
tester Model PurposeLuckyByGender Sut
…
This means we have (10*11)/2=55 cases for each gender, 2 steps (In, Out) per case means 110 steps and for both genders including last switch from 10F-to-M 221 steps in total. But TorXakis occasionally adds some Quiescence steps in between, so let’s run TorXakis for 300 steps instead. In TorXakis type the following command:
test 300
TXS >> .....1: OUT: No Output (Quiescence)
TXS >> .....2: IN: Act { { ( In, [ Person(Male,"Ac","Arv",13,5) ] ) } }
TXS >> .....3: OUT: Act { { ( Out, [ True ] ) } }
TXS >> .....4: OUT: No Output (Quiescence)
TXS >> .....5: IN: Act { { ( In, [ Person(Female,"B","D",19,7) ] ) } }
TXS >> .....6: OUT: Act { { ( Out, [ False ] ) } }
TXS >> .....7: OUT: No Output (Quiescence)
TXS >> .....8: IN: Act { { ( In, [ Person(Male,"D","H",29,7) ] ) } }
TXS >> .....9: OUT: Act { { ( Out, [ False ] ) } }
TXS >> ....10: OUT: No Output (Quiescence)
TXS >> ....11: IN: Act { { ( In, [ Person(Male,"F","O",30,1) ] ) } }
TXS >> ....12: OUT: Act { { ( Out, [ False ] ) } }
TXS >> ....13: OUT: No Output (Quiescence)
TXS >> ....14: IN: Act { { ( In, [ Person(Female,"A","D",2,3) ] ) } }
TXS >> ....15: OUT: Act { { ( Out, [ False ] ) } }
TXS >> ....16: OUT: No Output (Quiescence)
TXS >> ....17: IN: Act { { ( In, [ Person(Female,"C","Pxd",3,12) ] ) } }
TXS >> ....18: OUT: Act { { ( Out, [ False ] ) } }
TXS >> ....19: OUT: No Output (Quiescence)
...
TXS >> ...255: IN: Act { { ( In, [ Person(Male,"T","B",31,10) ] ) } }
TXS >> ...256: OUT: Act { { ( Out, [ False ] ) } }
TXS >> ...257: IN: Act { { ( In, [ Person(Female,"B","D",29,8) ] ) } }
TXS >> ...258: OUT: Act { { ( Out, [ True ] ) } }
TXS >> ...259: IN: Act { { ( In, [ Person(Female,"Yj","L",31,2) ] ) } }
TXS >> ...260: OUT: Act { { ( Out, [ False ] ) } }
TXS >> ...261: IN: Act { { ( In, [ Person(Female,"N","H",9,11) ] ) } }
TXS >> ...262: OUT: Act { { ( Out, [ False ] ) } }
TXS >> ...263: IN: Act { { ( In, [ Person(Female,"Pdp","A",5,7) ] ) } }
TXS >> ...264: OUT: Act { { ( Out, [ False ] ) } }
TXS >> ...265: IN: Act { { ( In, [ Person(Female,"Lh","H",30,11) ] ) } }
TXS >> ...266: OUT: Act { { ( Out, [ False ] ) } }
TXS >> ...267: IN: Act { { ( In, [ Person(Female,"Z","P",31,10) ] ) } }
TXS >> ...268: OUT: Act { { ( Out, [ False ] ) } }
TXS >> ...269: OUT: No Output (Quiescence)
TXS >> ...270: IN: Act { { ( In, [ Person(Female,"V","C",18,9) ] ) } }
TXS >> ...271: OUT: Act { { ( Out, [ False ] ) } }
TXS >> ...272: IN: Act { { ( In, [ Person(Female,"Hbx","H",30,1) ] ) } }
TXS >> ...273: OUT: Act { { ( Out, [ True ] ) } }
TXS >> ...274: IN: Act { { ( In, [ Person(Female,"D","K",18,1) ] ) } }
TXS >> ...275: OUT: Act { { ( Out, [ False ] ) } }
TXS >> ...276: OUT: No Output (Quiescence)
TXS >> ...277: IN: Act { { ( In, [ Person(Female,"Wp","Pkx",29,12) ] ) } }
TXS >> ...278: OUT: Act { { ( Out, [ False ] ) } }
TXS >> ...279: OUT: No Output (Quiescence)
TXS >> ...280: IN: Act { { ( In, [ Person(Male,"G","Ahagpa",14,4) ] ) } } <<== This is a Male after 10 Females
TXS >> ...281: OUT: Act { { ( Out, [ True ] ) } } <<== He's lucky based on gender
TXS >> ...282: OUT: No Output (Quiescence)
TXS >> ...283: IN: Act { { ( In, [ Person(Male,"F","A",30,8) ] ) } }
TXS >> ...284: OUT: Act { { ( Out, [ False ] ) } }
...
TXS >> ...299: IN: Act { { ( In, [ Person(Male,"M","P",23,6) ] ) } }
TXS >> ...300: OUT: Act { { ( Out, [ False ] ) } }
TXS >> PASS
Point for attention: In our repeatAndSwitchGender process we didn’t have to tell TorXakis that after switching the gender the next person has to be lucky on unlucky; we just enforced a certain sex to be assigned to current person. TorXakis knows what each person’s luckiness output should be depending on the Model.


This is a very simple angular application, using the marvel open api. It is only used as a sample application for the grunt-template


if len(trials) == 0:
logger.warning("Your study does not have any completed trials.")
return go.Figure(data=[], layout=layout)
data = go.Scatter3d(
x=[t.values[0] for t in trials],
y=[t.values[1] for t in trials],
trials = study.get_pareto_front_trials()
if len(trials) == 0:
raise ValueError("There must be one or more completed trials to plot a study.")
data = go.Scatter3d(
x=[t.values[0] for t in trials],
y=[t.values[1] for t in trials],


vargame=newPhaser.Game(800,600,Phaser.AUTO,'phaser-example',{preload:preload,create:create});functionpreload(){// Tilemaps are split into two parts: The actual map data (usually stored in a CSV or JSON file) // and the tileset/s used to render the map.// Here we'll load the tilemap data. The first parameter is a unique key for the map data.// The second is a URL to the JSON file the map data is stored in. This is actually optional, you can pass the JSON object as the 3rd// parameter if you already have it loaded (maybe via a 3rd party source or pre-generated). In which case pass 'null' as the URL and// the JSON object as the 3rd parameter.// The final one tells Phaser the format of the map data, in this case it's a JSON file exported from the Tiled map editor.// This could be Phaser.Tilemap.CSV too.game.load.tilemap('mario','assets/tilemaps/maps/super_mario.json',null,Phaser.Tilemap.TILED_JSON);// Next we load the tileset. This is just an image, loaded in via the normal way we load images:game.load.image('tiles','assets/tilemaps/tiles/super_mario.png');}varmap;varlayer;functioncreate(){game.stage.backgroundColor='#787878';// The 'mario' key here is the Loader key given in game.load.tilemapmap=game.add.tilemap('mario');// The first parameter is the tileset name, as specified in the Tiled map editor (and in the tilemap json file)// The second parameter maps this name to the Phaser.Cache key 'tiles'map.addTilesetImage('SuperMarioBros-World1-1','tiles');// Creates a layer from the World1 layer in the map data.// A Layer is effectively like a Phaser.Sprite, so is added to the display list.layer=map.createLayer('World1');// This resizes the game world to match the layer dimensionslayer.resizeWorld();}


Preparing for production
This time we’ve finished the blog engine. Let’s see the few common steps we need to put a Play application in production.
Defining a framework ID
You will typically deploy your application on a different computer (a server) than the one you used for development. So you will have a different Play installation.
Play allows to assign each framework installation a different ID, then to manage different configurations in the same application.conf
file. Let’s say that the server01
will host your production application.
Once the Play framework is installed on this server, let’s define the framework ID using the play id
command. Type:
$ play id
And assign server01
as id. Now we can define special keys in the yabe configuration file that will be used only when the application is running on the server.
Setting the application in PROD mode
The first configuration key we want specialize for the server deployment is the application.mode
property. So far we have used the DEV mode that allows Play to hot reload and recompile Java files and display detailed messages when an error occurs. In PROD mode however, Play will compile all Java sources and templates at startup time and will never check again for changes.
In the yabe/conf/application.conf
file, define:
%server01.application.mode=PROD
Now when you run the yabe application on the server, it will automatically start in PROD mode.
Configuring a MySQL server
For production use, we will use a MySQL server as database server instead of the in-memory H2 Database we have used so far. Play comes with the JDBC driver for MySQL so we don’t need to install anything more.
Edit the database configuration in the yabe/conf/application.conf
file:
%server01.db=mysql:root:secret@yabe
We will now tweak the way Hibernate manages the database schema for us. It’s very useful when Hibernate automatically updates the database schema as the Java model objects change.
Change the jpa.ddl
configuration key:
%server01.jpa.ddl=update
However it’s kind of unpredictable, and running magical things on a production database is never a good thing. So you should always have a backup before a new deployement. If you don’t want Hibernate to update your database, change the jpa.ddl
configuration key to validate
:
%server01.jpa.ddl=validate
Setting up a frontal HTTP server
Now we could just change the embedded HTTP server’s default port to 80 in order to have a real production server. However it will limit us to installing only one Play application on a given server. As we typically want to install several applications in the same server (but using different IP host names), we need to use a frontal HTTP server as reverse proxy.
You can choose any HTTP server and configure it as reverse proxy, however it is generally a good choice to take something light and fast like LIGHTTPD.
The exact configuration of LIGHTTPD is beyond the scope of this tutorial, but should be something like:
server.modules = (
"mod_access",
"mod_proxy",
"mod_accesslog"
)
…
$HTTP["host"] =~ "www.yabe.com" {
proxy.balance = "round-robin" proxy.server = ( "/" =>
( ( "host" => "<IP_ADDRESS>", "port" => 9000 ) ) )
}
And then allow a local reverse proxy to connect to your Play application by adding this key to the application.conf
file:
%server01.XForwardedSupport=<IP_ADDRESS>
This is just the beginning
If you have read and followed this tutorial, you’re now a seasoned Play developer. You know most of the concepts that drive Play application development.
At this stage, you may want to continue the tutorial with internationalisation and localisation.
There are still more features we haven’t explored yet, especially related to Web services, like JSON or XML. Also Play comes with more modules that provide more features. And Play itself still evolves every day.
If you are convinced that Play will help you save time for your next Java web application, you’re now ready to start. And don’t hesitate to ask us any question on the Play Google Group.
Thank you!


Hello.
I am Jones
-I am a creative, freelace full stack developer based in Austin TX.
JL
My Work
.Persona - Helps clients find the appropriate freelancing services to make their ideas into reality.
Travel Journal - Social Media Network to allow for creation of Trip Journals to share with family and friends!
- 03
- work
-
role
Developer & Design
-
made
2021
- Go to website
Ether Arcade - Online archade, pay 25¢ and get the highscore and win the jackpot!


Owen couldn’t figure out how to easily and quickly move posts from the old wordpress site to this one. Here they all are as pdfs of the wordpress posts.
- About fairness in the workplace.
- About p-values.
- Back garden camera trap.
- Global net change in local plant biodiversity.
- Graduation day!
- Group retreat 2016.
- How to read ANCOVA summary tables in R.
- IEU Photo-Exhibition.
- Interesting papers 1.
- Interesting papers 2.
- Interesting papers 3.
- Interesting papers 4.
- Interesting papers 5.
- Interesting papers 6.
- Interesting papers 7.
- Interesting papers 8.
- Interesting papers 9.
- Interesting papers 10.
- Interesting papers 11.
- Interesting papers 12.
- My first flipped classroom course.
- Peer review in performance appraisals.
- Predation matrices.
- Random resources 1.
- Some books.
- Some notes on Principal Component Analysis.
- Testing the Metabolic Theory of Ecology_ a simple pipeline using R_.
- The art of advertising science-elevator pitches.
- When should I start giving.


Toggle navigation
Ready to be cooked
Gourmet Selection
Two microservices for customers and stores - Spring Cloud Samples
Spring Cloud Example Project - Kenny Bastani
Spring Cloud Stream Sample Applications - Spring Cloud


In this blog post, I would like to show you how easy is to publish your docker images to GitHub Container Registry. This topic is relevant because Docker Hub has changed retention limits, so might want to consider other players on the market.
TL;DR
To publish an image to ghcr:
- Create a Personal Access Token
- Log-in to the container registry
- Push an image to
ghcr.io/GITHUB_USERNAME/IMAGE_NAME:VERSION
To access GitHub container registry you need to create Personal Access Token (PAT) on GitHub:
“Settings > Developer Settings > Personal access tokens” and create token with permissions related to “packages” (or https://github.com/settings/tokens/new).
After that, you can login export CR_PAT=YOUR_TOKEN ; echo $CR_PAT | docker login ghcr.io -u USERNAME --password-stdin
.
Now, you want to tag your local images:
docker tag SOURCE_IMAGE_NAME:VERSION ghcr.io/TARGET_OWNER/TARGET_IMAGE_NAME:VERSION
Push re-tagged imaged to the container registry (ghcr.io):
docker push ghcr.io/OWNER/IMAGE_NAME:VERSION
Example
I’ve pushed a containerized image of dotnet-script to GitHub Registry, it allows you to run REPL-style prompt for C#.
For now, GitHub doesn’t provide search and discovery capabilities for images, but you already can find some UI to see image details from UI, if you know the name.
You can find packaged dotnet-script here:
https://github.com/users/NikiforovAll/packages/container/package/dotnet-script
🚀 Let’s download and run it:
docker image pull ghcr.io/nikiforovall/dotnet-script:latest
docker container run --it --rm ghcr.io/nikiforovall/dotnet-script


| |
Methods defined here:
- __init__(self, url, key, tokenizer, rho_threshold)
- Constructor
@param {String} url, url to tagme api
@param {String} key, authorization token
@param {String} tokenizer, path to tokenizer in a certain language
@param {Double} rho_threshold, threshold for rho
- gen_build_snippets(self, data)
- Generator that builds snippets out of the sentences in a doc,
such that the api can handle the amount of data
@param {Generator} data, sequence of docs
- gen_split_into_sentences(self, data)
- Generator that uses nltk for splitting textual data into sentences
@param {Generator} data, sequence of docs
- gen_tag_snippets(self, data)
- Generator that sends textual snippets to the api of the entity linker
and adds the result to the data structure if the rho is above a given
threshold
@param {Generator} data, sequence of docs
Data descriptors defined here:
- __dict__
- dictionary for instance variables (if defined)
- __weakref__
- list of weak references to the object (if defined)
|


{% extends "base.html" %}
{% block content %}
Feature Request Form
Title
*
Descripiton
Client
*
Client A
Client B
Client C
Client Priority
*
Target Date
Product Area
*
Policies
Billing
Claims
Reports
Submit
List of Feature Requests
{% endblock %}


WELCOME TO THE DOLLHOUSE A film review by Michael John Legeros Copyright 1996 Michael John Legeros
(Sony) Directed by Todd Solondz Written by Todd Solondz Cast Heather Matarazzo, Brendan Sexton Jr., Matthew Faber, Daria Kalinina, Eric Mabius, Bill Buell, Angela Pietropinto, Scott Coogan MPAA Rating "R" (presumably for language) Running Time 93 minutes Reviewed at The Rialto, Raleigh, NC (22JUN96)
==
First-time writer/director/producer Todd Solondz won Best Picture at the Sundance Film Festival with this cute, cutting, and very black comedy about a seventh-grade girl desperately trying to survive in Junior High Hell. Newcomer Heather Matarazzo touches the heart as the tragic Dawn Weiner, huh huh huh, the bespectacled school outcast who is repeatedly dumped upon by her teachers, friends, and family. Though nowhere near as funny as the rave reviews have suggested-- any episode of "The Simpsons" crackles with more knowing wit-- WELCOME TO THE DOLLHOUSE still succeeds as both a character comedy and a social satire. As in Larry Clark's KIDS, the story situations-- and the accompanying language-- are also brutally frank. Pay attention to the psychology behind a young man's threat of sexual violence and Dawn's response to same. I'm tempted to label this movie as "anti-Disney" or, if you prefer, the antithesis of mainstream family fare. However, as Mickey owns Mirimax, the corporate giant could well be the next home for Mr. Solondz and his remarkable talents.
Grade: B+
--
Mike Legeros - Raleigh, NC
<EMAIL_ADDRESS>(h) -<EMAIL_ADDRESS>(w)
Visit me in MOVIE HELL
The review above was posted to the
rec.arts.movies.reviews newsgroup (de.rec.film.kritiken for German reviews).
The Internet Movie Database accepts no responsibility for the contents of the
review and has no editorial control. Unless stated otherwise, the copyright
belongs to the author.
Please direct comments/criticisms of the review to relevant newsgroups.
Broken URLs inthe reviews are the responsibility of the author.
The formatting of the review is likely to differ from the original due
to ASCII to HTML conversion.
Related links: index of all rec.arts.movies.reviews reviews


publications
Publications by categories in reversed chronological order. Generated by jekyll-scholar.
2013
-
Physical principles for scalable neural recording Frontiers in computational neuroscience 2013
2014
-
Decide now or decide later?: Quantifying the tradeoff between prospective and retrospective access decisions In Proceedings of the 2014 ACM SIGSAC Conference on Computer and Communications Security 2014
2015
-
Spatial information in large-scale neural recordings Frontiers in computational neuroscience 2015
2017
-
Nucleotide-time alignment for molecular recorders PLoS computational biology 2017
-
Toward the Statistical and Biological Realization of DNA Polymerase as a Molecular Recorder 2017
-
Scalable passive sleep monitoring using mobile phones: opportunities and obstacles Journal of medical Internet research 2017
2018
-
High-resolution mapping of DNA polymerase fidelity using nucleotide imbalances and next-generation sequencing Nucleic acids research 2018
-
Development of novel metabolite-responsive transcription factors via transposon-mediated protein fusion Protein Engineering, Design and Selection 2018


Loading notifications ...
No notifications yet.
{{notification.name}}
Ooops! Something went wrong :-( {{vm.errmsg}}


--- layout: post authors: ["Shoaib Sufi"] title: "Software Credit Workshop in London, 19 October 2015" date: 2015-09-18 time: "08:00:00" tags: ["Community"] ---
Securing credit for research software is the subject of the Software Credit Workshop. This is taking place at the Natural History Museum, London, UK on the 19th October 2015.
Explore what contributions software can and should make for career advancement. Discuss ways in which you see software tools and applications supporting the current needs of researchers and software developers seeking credit for their involvement in research software. Identify and propose ideas for improving the way software’s contribution to better research are connected and how this should support appropriate reputational credit for research software enablers.
Join other funders, publishers, software developers, researchers, leaders, citation experts and altmetrics visionaries to make your thoughts heard and shape the conversation.
Find out more and register at www.software.ac.uk/software-credit.


InfluxViz is a set of client-side visualisation tools for an InfluxDB. The project is inspired by Influga and Grafana and is intended to power a similar dashboard designed specifically for influxdb.
Primarily intended for use by HyveDev, a home monitoring and automation solution, this software is MIT licensed and available for all users. Pull requests and help are welcome!