If you intend to use the various Qlik script snippets included in the GithHub repository, you first need to initialize things.
Initializing Butler in an app’s load script is easy, just call the ButlerInit function.
Note: It’s usually a good idea to create a shared data connection for scripts that are available to all Sense apps.
In the example below this shared data connection is simply called “Butler scripts”:
1 - Swagger UI: Try out the Butler API using the API docs
Assuming Butler is properly configured and running, it’s easy to try out Butler’s API.
This page shows some examples of interactions with the Butler API.
Below are some examples of how Butler’s built-in Swagger docs can be used to test-drive the Butler API.
Note: Some of the videos below were created with older Butler versions.
Details may have changed (for example what API parameters are available), the general concepts remain the same though.
OpenAPI documentation built into Butler
The complete documentation for Butler’s REST API is built into Butler itself.
This means that its very easy to try out and get familiar with the various API endpoints, without having to create Sense apps for everything you want to try out.
If Butler’s config file contains the settings below, the API will be available at http://<IP_ADDRESS>:8080.
In addition to the API endpoints, the API documentation will be available at http://<IP_ADDRESS>:8080/documentation.
The beauty of the Swagger docs is that you can also test drive the API itself. If you have Butler running it’s thus super easy to test the various REST API endpoints.
The API doc page looks like this:
Other tools for exploring APIs
If the OpenAPI interface to Butler’s API feels limited, there are lots of tools dedicated to this task.
Two good ones are:
Paw is Mac only, costs a bit of money, but is very, very good. Highly recommended.
Create, query, edit and delete task reload schedules using Butler’s scheduling API.
When wathcing the video below, you will notice there are two pre-defined schedules.
One of them fires every 30 seconds and this is also visible in the Butler logs:
List available Sense apps and extract them as JSON
List existing apps on Sense server, then export one of them to JSON.
2 - Flexible scheduling of Sense reload tasks
Examples showing how to use the Butler scheduler using direct API calls.
There are many ways to call REST APIs. In this page curl is used, but the same tests can be done using Paw, Postman and by using the REST connector from within Qlik Sense load scripts.
All the examples assume Butler is exposing it’s API on <IP_ADDRESS>:8080.
List all defined schedules
Looks like there is currently one schedule:
➜ ~ curl "http://<IP_ADDRESS>:8080/v4/schedules"| json_pp
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
10030610030600164980 --:--:-- --:--:-- --:--:-- 20400[{"created" : "2021-10-08T07:24:38.373Z",
"cronSchedule" : "* */2 * * *",
"id" : "3702cec1-b6c8-463e-bda3-58d6a94dd9ac",
"lastKnownState" : "started",
"name" : "Every 2 hours",
"qlikSenseTaskId" : "0fe447a9-ba1f-44a9-ac23-68c3a1d88d8b",
"startupState" : "started",
"tags" : ["tag 3",
"abc 123 åäö"],
"timezone" : "Europe/London"}]➜ ~
Get a specific schedule
Let’s try to get a schedule that doesn’t exist:
➜ ~ curl "http://<IP_ADDRESS>:8080/v4/schedules?id=Manually-added-schedule-1"| json_pp
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
10011710011700145630 --:--:-- --:--:-- --:--:-- 29250{"error" : "Bad Request",
"message" : "REST SCHEDULER: Schedule ID Manually-added-schedule-1 not found.",
"statusCode" : 400}➜ ~
Here’s a schedule that does exist (as per the API call above):
➜ ~ curl "http://<IP_ADDRESS>:8080/v4/schedules?id=3702cec1-b6c8-463e-bda3-58d6a94dd9ac"| json_pp
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
10035410035400504990 --:--:-- --:--:-- --:--:-- 115k
{"created" : "2021-10-08T07:24:38.373Z",
"cronSchedule" : "* */2 * * *",
"id" : "3702cec1-b6c8-463e-bda3-58d6a94dd9ac",
"lastKnownState" : "started",
"name" : "Every 2 hours",
"qlikSenseTaskId" : "0fe447a9-ba1f-44a9-ac23-68c3a1d88d8b",
"startupState" : "started",
"tags" : ["tag 3",
"abc 123 åäö"],
"timezone" : "Europe/London"}➜ ~
Add new schedule
Note how we get back information about the newly created schedule. It’s the same data that was sent to the API method, with the addition of schedule id, created timestamp and last known state.
Looking in the Butler logs we see that the every-5-seconds schedule with an ID ending in …a300 indeed fires every 5 seconds:
Starting and stopping a schedule
Let’s stop the schedule we just created:
➜ ~ curl -X "PUT""http://<IP_ADDRESS>:8080/v4/schedules/b028d0a2-7116-41bf-b15a-4f01bd126464/stop"| json_pp
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
10021002002460 --:--:-- --:--:-- --:--:-- 500{}➜ ~
If we get info about this schedule, it should have lastKnownState=stopped… Let’s verify.
➜ ~ curl "http://<IP_ADDRESS>:8080/v4/schedules?id=fb9b16f1-e2cf-4291-8036-24ef90efa300"| json_pp
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
10030710030700 99k 0 --:--:-- --:--:-- --:--:-- 99k
{"created" : "2020-10-16T15:23:36.957Z",
"cronSchedule" : "*/5 * * * * *",
"id" : "fb9b16f1-e2cf-4291-8036-24ef90efa300",
"lastKnownState" : "stopped",
"name" : "Every 5 sec",
"qlikSenseTaskId" : "0fe447a9-ba1f-44a9-ac23-68c3a1d88d8b",
"startupState" : "started",
"tags" : ["tag 1",
"abc 123 åäö"],
"timezone" : "Europe/Stockholm"}➜ ~
Great!
As a final step, let’s start the schedule again, as well as verifying it was successfully started:
➜ ~ curl -X "PUT""http://<IP_ADDRESS>:8080/v4/schedules/fb9b16f1-e2cf-4291-8036-24ef90efa300/start"| json_pp
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
10030910030900772500 --:--:-- --:--:-- --:--:-- 77250[{"created" : "2020-10-16T15:23:36.957Z",
"cronSchedule" : "*/5 * * * * *",
"id" : "fb9b16f1-e2cf-4291-8036-24ef90efa300",
"lastKnownState" : "started",
"name" : "Every 5 sec",
"qlikSenseTaskId" : "0fe447a9-ba1f-44a9-ac23-68c3a1d88d8b",
"startupState" : "started",
"tags" : ["tag 1",
"abc 123 åäö"],
"timezone" : "Europe/Stockholm"}]➜ ~ curl "http://<IP_ADDRESS>:8080/v4/schedules?id=fb9b16f1-e2cf-4291-8036-24ef90efa300"| json_pp
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
10030710030700 149k 0 --:--:-- --:--:-- --:--:-- 149k
{"created" : "2020-10-16T15:23:36.957Z",
"cronSchedule" : "*/5 * * * * *",
"id" : "fb9b16f1-e2cf-4291-8036-24ef90efa300",
"lastKnownState" : "started",
"name" : "Every 5 sec",
"qlikSenseTaskId" : "0fe447a9-ba1f-44a9-ac23-68c3a1d88d8b",
"startupState" : "started",
"tags" : ["tag 1",
"abc 123 åäö"],
"timezone" : "Europe/Stockholm"}➜ ~
All good!
3 - Reload task chaining with parameters
Examples showing how to use Butler’s key-value store to pass parameters between apps in a reload chain, using calls to Butler’s API.
Reload chaining with parameters à la Butler
First: Some people argue that apps in an ETL chain should be atomic and not pass parameters to each other.
There is certainly some merit to this view, but there are also cases where you just have to tell the following app(s) what happened in a previous step in the reload chain. Some kind of parameter passing is thus needed.
Passing parameters between apps in a QMC reload chain can be done in various ways.
The most common option is to use what’s available in Sense out of the box:
Store the parameters in a disk file (CSV, QVD etc) in the first app, then load the parameters back into the second app when it is reloading.
Butler offers a different approach: Store and manipulate named key-value pairs within Butler, using its REST API.
It works like this:
Pretty easy, right?
One more thing. There is an optional but useful property for each KV pair: TTL, or time-to-live.
If a ttl is set (in milliseconds) for a KV pair, it will be automatically deleted when the ttl clock expire. This is an easy way to keep the Butler key-value store nice and tidy.
Data connections not included
In order to call Butler’s REST API you need a couple of REST data connections defined in Qlik Sense. The apps described in this example assumes Butler_Get and Butler_POST exists. They look like this:
Butler_GET
This data connection is trivial. When creating it any REST API that responds to GET requests can be used. Later on (before the calls to the Butler API) the URL will be replaced with the correct one = host:port where Butler is running.
Butler_POST
This data connection is a bit more complex.
First, in order to create the connection you need a REST endpoint that takes a POST with data passed in the body of the message. The data connection used by the apps in this example are found below. Note the http method, the request body and the Content-Type Query header. Any other settings can be ignored.
Secondly, Qlik Sense’s REST connector only supports GET and POST methods over http. That’s fine in this particular case, because we’ll use a POST to create a new key-value pair. On a generel levels it’s however really quite bad that Qlik’s REST connector only supports GET and POST: PUT, DELETE and other http methods are certainly also used out there on the Internet, and should be supported too.
Some of the Butler API endpoints use PUT or DELETE methods, which is nothing strange at all - rather the opposite. Butler tries to follow best practices when it comes to using GET, POST, PUT and DELETE at the appropriate times.
We still need a way to invoke PUT and DELETE endpoints from Sense load script.
This is done in the script, by adding an extra http header in the call to Butler’s API: X-HTTP-Method-Override
If X-HTTP-Method-Override is set to PUT in the call to Butler’s API, the Butler will convert the call to a PUT call before it reaches the message dispatching within Butler. Same thing for DELETEs.
Parameter passing in action
The scenario is as follows:
App 1 needs to pass a parameter called “Paramater 1” to App 2
App 2 is scheduled to reload either directly or in some later stage after App 1.
App 1 stores the parameter in Butler’s key-value store during reload of App 1.
When App 2 reloads it pulls the parameter from the KV store.
When App 1 reloads the reload window looks like this. Note how the app has created a key-value pair within Butler.
App 2 is scheduled to reload when App 1 has finished reloading. Note that we get back the same value that was set by App 1. Mission accomplished.
Qlik script for passing parameters between apps
Let’s take a closer look at the two apps. The apps are available in the sense_apps directory of the Butler repository on GitHub.
The apps are called Butler 4.0 - Reload chain parameters, app 1.qvf and Butler 4.0 - Reload chain parameters, app 2.qvf.
App 1
The app has three script sections, each is shown below.
Script section 1: Init
The interesting parts here are the two variables towards the end. These tell the rest of the script where Butler is running.
SET ThousandSep=',';
SET DecimalSep='.';
SET MoneyThousandSep=',';
SET MoneyDecimalSep='.';
SET MoneyFormat='$#,##0.00;-$#,##0.00';
SET TimeFormat='h:mm:ss TT';
SET DateFormat='M/D/YYYY';
SET TimestampFormat='M/D/YYYY h:mm:ss[.fff] TT';
SET FirstWeekDay=6;
SET BrokenWeeks=1;
SET ReferenceDay=0;
SET FirstMonthOfYear=1;
SET CollationLocale='en-US';
SET CreateSearchIndexOnReload=1;
SET MonthNames='Jan;Feb;Mar;Apr;May;Jun;Jul;Aug;Sep;Oct;Nov;Dec';
SET LongMonthNames='January;February;March;April;May;June;July;August;September;October;November;December';
SET DayNames='Mon;Tue;Wed;Thu;Fri;Sat;Sun';
SET LongDayNames='Monday;Tuesday;Wednesday;Thursday;Friday;Saturday;Sunday';
SET NumericalAbbreviation='3:k;6:M;9:G;12:T;15:P;18:E;21:Z;24:Y;-3:m;-6:μ;-9:n;-12:p;-15:f;-18:a;-21:z;-24:y';
// The Butler instance is running at this IP/port:
let vButlerHost = '<IP_ADDRESS>';
let vButlerPort = '8080';
Script section 2: Sub definitions
Here we define two subs: One to get a bit more friendly looking trace messages, and one that encapsulates the code needed to store key-value pairs in Butler.
// ------------------------------------------------------------
// ** Time stamped trace messages **
//
// Get nice trace lines in the reload log by calling the line with
// CALL NiceTrace('My trace message. Variable value=$(vVariableName)');
//
// Paramaters:
// vMsg : Message sent to reload log
// ------------------------------------------------------------
sub NiceTrace(vMsg)
let vNow = Now(1);
TRACE >>> $(vNow): $(vMsg);
// Clear timestamp variable
set vNow=;
end sub
// ------------------------------------------------------------
// ** Add key-value pair to a namespace **
//
// Paramaters:
// vNamespace : Namespace in which the KV pair will be stored
// vKey : Key name
// vValue : Value to store together with key
// vTimeToLive : How long should the KV pair exist before being automatically deleted?
// Set to 0 to disable TTL feature (=no auto-delete of KV pair)
// ------------------------------------------------------------
sub AddKeyValue(vNamespace, vKey, vValue, vTimeToLive)
LIB CONNECT TO 'Butler_POST';
if (vTimeToLive>0) then
let vRequestBody = '{"key": "$(vKey)", "value": "$(vValue)", "ttl": "$(vTimeToLive)"}';
else
let vRequestBody = '{"key": "$(vKey)", "value": "$(vValue)"}';
end if
// Escape " in request body
let vRequestBody = replace(vRequestBody,'"', chr(34)&chr(34));
RestConnectorMasterTable:
SQL SELECT
"namespace",
"key",
"value",
"ttl"
FROM JSON (wrap on) "root"
WITH CONNECTION (
Url "http://$(vButlerHost):$(vButlerPort)/v4/keyvalues/$(vNamespace)",
BODY "$(vRequestBody)",
HTTPHEADER "Content-Type" "application/json"
);
DROP TABLE RestConnectorMasterTable;
end sub
Script section 3: Write parameters to KV store
Finally, the code needed to actually store the parameter in Butler is just a few lines:
Set host and port where Butler is running. Exactly the same script as in App 1.
SET ThousandSep=',';
SET DecimalSep='.';
SET MoneyThousandSep=',';
SET MoneyDecimalSep='.';
SET MoneyFormat='$#,##0.00;-$#,##0.00';
SET TimeFormat='h:mm:ss TT';
SET DateFormat='M/D/YYYY';
SET TimestampFormat='M/D/YYYY h:mm:ss[.fff] TT';
SET FirstWeekDay=6;
SET BrokenWeeks=1;
SET ReferenceDay=0;
SET FirstMonthOfYear=1;
SET CollationLocale='en-US';
SET CreateSearchIndexOnReload=1;
SET MonthNames='Jan;Feb;Mar;Apr;May;Jun;Jul;Aug;Sep;Oct;Nov;Dec';
SET LongMonthNames='January;February;March;April;May;June;July;August;September;October;November;December';
SET DayNames='Mon;Tue;Wed;Thu;Fri;Sat;Sun';
SET LongDayNames='Monday;Tuesday;Wednesday;Thursday;Friday;Saturday;Sunday';
SET NumericalAbbreviation='3:k;6:M;9:G;12:T;15:P;18:E;21:Z;24:Y;-3:m;-6:μ;-9:n;-12:p;-15:f;-18:a;-21:z;-24:y';
// The Butler instance is running at this IP/port:
let vButlerHost = '<IP_ADDRESS>';
let vButlerPort = '8080';
Script section 2: Sub definitions
Here we define a NiceTrace sub, and a sub for retrieving key-value pairs from Butler.
// ------------------------------------------------------------
// ** Time stamped trace messages **
//
// Get nice trace lines in the reload log by calling the line with
// CALL NiceTrace('My trace message. Variable value=$(vVariableName)');
//
// Paramaters:
// vMsg : Message sent to reload log
// ------------------------------------------------------------
sub NiceTrace(vMsg)
let vNow = Now(1);
TRACE >>> $(vNow): $(vMsg);
// Clear timestamp variable
set vNow=;
end sub
// ------------------------------------------------------------
// ** Get key-value pair from a namespace **
//
// Paramaters:
// vNamespace : Namespace in which the KV pair will be stored
// vKey : Key name
// vResultVarName : Name of variable in wich value will be placed
// ------------------------------------------------------------
sub GetKeyValue(vNamespace, vKey, vResultVarName)
LIB CONNECT TO 'Butler_GET';
RestConnectorMasterTable:
SQL SELECT
"key",
"value"
FROM JSON (wrap on) "root"
WITH CONNECTION (
Url "http://$(vButlerHost):$(vButlerPort)/v4/keyvalues/$(vNamespace)?key=$(vKey)"
);
let $(vResultVarName) = Peek('value', 0, 'RestConnectorMasterTable');
set vResultVarName=;
DROP TABLE RestConnectorMasterTable;
end sub
Script section 3: Read parameter from KV store
Again, the code needed to interact with the key-value API is pretty compact:
// Define variable to store the retrieved parameter in
let vParam1='';
Call NiceTrace('---------------------------')
Call NiceTrace('Loading parameter from Butler key-value store.')
Call GetKeyValue('Reload chain parameter demo', 'Parameter 1', 'vParam1')
Call NiceTrace('Retrieved parameter value:')
Call NiceTrace('Namespace="Reload chain parameter demo", Key="Parameter 1", Value="$(vParam1)"')
set vParam1=;
4 - Monitoring Butler's memory usage using Grafana
Butler can be configured to store its own memory usage in InfluxDB. Here we look at how this works and how Grafana real-time charts can be created.
Butler 4.0 adds several new features, one being the uptime messages that can be optionally posted to the logs. Each message tells how long Butler has been running and how much memory it is using right then.
This information can also, again optionally, be stored in InfluxDB or New Relic.
InfluxDB is a database for time-series data such as measurements, while New Relic is enterprise grade, SaaS observability solution.
Once in InfluxDB it’s easy to create nice monitoring charts in Grafana or similar tools. New Relic has their own built-in dashboard tool (but Grafana can actually load data from New Relic too!).
But hey - why spend CPU cycles and disk space on this?
Well, if you are serious about your Qlik Sense Enterprise environment, you should also be serious about your supporting tools and microservices, Butler included.
Even though Butler over the years has proven to be a very stable piece of software, there is always the risk of new features misbehaving or new bugs appearing.
It’s thus a good idea to monitor for example how much memory (RAM) tools like Butler use over time and alert if things go wrong.
Enable Butler’s uptime monitor
Both he uptime monitor and the logging to desired destination (InfluxDB or New Relic) must be enabled. Note that there are two settings for this. If your InfluxDB uses authentication you’ll need to enable this too in Butler’s config file.
If you use New Relic to monitor your uptime metrics you must first define the New Relic API credentials in the Butler config file’s Butler.thirdPartyToolsCredentials.newRelic settings, then configure the uptime monitoring specifics in Butler.uptimeMonitor.storeNewRelic.
The uptime monitoring part of the config file could looks like this:
# Uptime monitoruptimeMonitor:enable:false# Should uptime messages be written to the console and log files?frequency:every 15 seconds # https://bunkat.github.io/later/parsers.htmllogLevel:verbose # Starting at what log level should uptime messages be shown?storeInInfluxdb:enable:false# Should Butler memory usage be logged to InfluxDB?hostIP:<IP or host name> # Where is InfluxDB server located?hostPort:8086# InfluxDB portauth:enable:false# Does InfluxDB require login?username:user_joe password:joesecretdbName:butler # Name of database in InfluxDB to which Butler's data is writteninstanceTag:DEV # Tag that can be used to differentiate data from multiple Butler instances# Default retention policy that should be created in InfluxDB when Butler creates a new database there. # Any data older than retention policy threshold will be purged from InfluxDB.retentionPolicy:name:10dduration:10dstoreNewRelic:enable:falsedestinationAccount:- First NR account- Second NR account# There are different URLs depending on whther you have an EU or US region New Relic account.# The available URLs are listed here: https://docs.newrelic.com/docs/accounts/accounts-billing/account-setup/choose-your-data-center/# As of this writing the options for the New Relic metrics API are# https://insights-collector.eu01.nr-data.net/metric/v1# https://metric-api.newrelic.com/metric/v1 url:https://insights-collector.eu01.nr-data.net/metric/v1 # Where should uptime data be sent?header:# Custom http headers- name:X-My-Headervalue:Header valuemetric:dynamic:butlerMemoryUsage:enable:true# Should Butler's memory/RAM usage be sent to New Relic?butlerUptime:enable:true# Should Butler's uptime (how long since it was started) be sent to New Relic?attribute:static:# Static attributes/dimensions to attach to the data sent to New Relic.- name:metricTypevalue:butler-uptime- name:servicevalue:butler- name:environmentvalue:proddynamic:butlerVersion:enable:true# Should the Butler version be included in the data sent to New Relic
Creating a InfluxDB database
When starting Butler for the first time and InfluxDB is enabled, it will connect to InfluxDB and if needed create a new database called butler, together with a retention policy called 10d:
Note that the only thing needed is a running InfluxDB instance. Butler creates the database in InfluxDB if needed, together with a retention policy that is defined in the Butler config file.
Hey data, are you there?
So far so good. Let’s wait a few minutes and then verify that New Relic and/or InfluxDB has received a few dataspoints. There should be data with 15 second intervals, to be precise.
Using the InfluxDB command line client to connect to InfluxDB we can do a manual query:
Indeed, there are a few data points in InfluxDB. Butler’s uptime monitor seems to be working.
Butler + InfluxDB + Grafana = 🎉📈
Grafana has excellent support for InfluxDB, it’s therefore a good way to visualise Butler memory use over time.
To use the Grafana dashboard included in the Butler GitHub repository you first need to create a Grafana data source named Butler ops metrics, and point it to the InfluxDB database in which Butler stores its data.
Once the Grafana data source is in place and working you can import the Grafana dashboard file Butler operational metrics.json (available in the docs/grafana folder in the GitHub repo).
If everything works you’ll see something like this:
Looks like Butler is using ca 70 MByte here. This is pretty normal, memory usage is usually around 100 MByte, even when Butler has been running for days, weeks and months. Exact memory usage will vary depending on which features are enabled.
Butler + New Relic = 😎🌟
While InfluxDB combined with Grafana is hard to beat when it comes to flexibility and look’n’feel of the dashboards, New Relic is outstanding when it comes to ease of setup.
New Relic is a SaaS product which means you don’t have to host neither databaes nor dashboard tool yourself.
It’s all there within New Relic.
What about cost? Is New Relic expensive?
Well, if you have lots of metrics, log files etc New Relic can become quite expensive as they charge you based on how much data you send to New Relic.
But given that Butler will send very little data you are unlikely to ever reach the limit of New Relic’s free tier.
There is thus a good chance you won’t even have to pay for New Relic if you only use it to monitor Butler.
A New Relic chart showing Butler memory usage can look like this:
5 - Start Sense tasks using Butler APIs
5.1 - Start Sense tasks using REST API
Use Butler’s REST API to start Sense tasks
If the Butler config file is properly set up it’s possible to start Sense tasks by doing a PUT or POST call to /v4/reloadtask/{taskId}/start endpoint.
A great use case is to have upstream systems that feed Qlik Sense with data trigger a Sense task when new data is available.
That way Sense doesn’t have to poll for new data, with less system resources used in both upstream system and in Sense.
AND users get the new data as quickly as possible!
General principles
The API docs contain the best info for how the API works, a few things to keep in mind though:
Butler will verify that all specified task IDs exist before trying to start them. Invalid task IDs will be reported in the http response.
If the allTaskIdsMustExist URL parameter is set to true it means that all specified task IDs must be valid for any of them to be started.
Tasks associated with tags and custom properties are not affected by the allTaskIdsMustExist flag.
Requirements
These config file settings must be set up before Butler can use the REST API to start tasks:
Configure Butler’s REST server:
Butler.restServerConfig.enable: true
Butler.restServerConfig.serverHost: <IP or hostname where Butler’s REST server is running>
Two tasks, specified in the request body, were started.
Start multiple tasks using task IDs, all task IDs must exist, task filtering ON
Here two task IDs are valid and on the list of approved task IDs. One task ID is invalid (too short).
As allTaskIdsMustExist=true we expect that no task is started (all task IDs must exist for any task to be started based on task ID!).
Task filtering is turned on in the config file’s Butler.startTaskFilter.enable entry.
One invalid (too short!) task is returned in the response.
As there was one or more invalid task IDs, the two valid and approved task IDs were not started.
Their task IDs are returned in the denied array in the response.
Start multiple tasks using task IDs, all task IDs must exist, task filtering OFF
Here two task IDs are valid and on the list of approved task IDs. One task ID is invalid (too short).
As allTaskIdsMustExist=true we expect that no task is started (all task IDs must exist for any task to be started based on task ID!).
Task filtering is turned off in the config file’s Butler.startTaskFilter.enable entry.
The response and its message is the same as in the previous example:
No tasks were started based on task IDs.
One invalid (too short!) task is returned in the response.
As there was one or more invalid task IDs, the two valid and approved task IDs were not started.
Their task IDs are returned in the denied array in the response.
Start multiple tasks using task IDs, task filtering ON
Two task IDs are valid and on the list of approved task IDs.
One task ID is valid but not on list of approved task IDs.
One task ID is invalid (too short).
Task filtering is turned on in the config file’s Butler.startTaskFilter.enable entry.
As the task “Reload task of App2” had both values set for the custom property, this task was started twice.
Sending parameters to apps
Sometimes there is a need to send parameters from outside of Sense to an app that should be reloaded.
This is supported by Butler as follows:
Start a task and pass in one or more key-value pairs (=the parameters that should be sent to the app(s)) in the body of the call.
Have the app being reloaded read the key-value pairs from within the load script, using the Butler APIs.
Optional: Clear up (delete KV pairs or the namespace used) the key-value store when done.
Here a single task, identified by its ID in the URL, is started.
Two key-value pairs are passed along as parameters to the app. One has a TimeToLive of 10 seconds, the other has no TTL (=it will not be automatically deleted).
Task filtering is off, i.e. any task can be started using this API.
5.2 - Start Sense tasks from load script of Sense apps
Helper functions included
It is very much possible to call Butler’s REST API from the load script of Sense apps.
Create a REST connector in the Sense editor, configure it for the endpoint you want to call and use it from the load script.
This works but is tedious and quickly leads to lots of script code - especially if you need to make many calls to the Butler API.
To make things a bit easier the Butler GitHub repository includes a set of helper .qvs files.
These contain functions/subs that encapsulate various Butler APIs (include starting tasks) and make them easier to use.
Just include the butler_subs.qvs file from the GitHub release package and you get (among many other things) a helper function that’s called StartTask.
Requirements for starting tasks via REST API
These config file settings must be set up before Butler can use the REST API to start tasks:
Connection to Qlik Sense:
Butler.configQRS.*
Configure Butler’s REST server:
Butler.restServerConfig.enable: true
Butler.restServerConfig.serverHost: <IP or hostname where Butler’s REST server is running>
Sense data connections as described in the Getting started section.
Helper functions
There are two helper functions/sub for starting tasks:
StartTask(...) is a generic function that can be called with a single task ID, or with complex combinations of task IDs, tags, custom properties and key-value pairs.
StartTask_KeyValue(...) makes it easy to start a single task and pass along one key-value pair as parameter. This function is essentially a specialized version of the more generic StartTask sub.
Start a single task
The function(=sub in Sense lingo) StartTask takes a single taskId parameter, which means that starting a reload task from an app’s load script is as simple as
Call StartTask(<TaskId>)
The demo app Butler 8.4 demo app.qvf (link) contains such a demo (and many others).
Need to pass along parameters to a task? There’s a Sub for that!
Sometimes you need to send parameters to a reload task (or rather to the load script of the app associated with the task).
This can be done by using the StartTask_KeyValue helper function/Sub.
That Sub takes a taskId as parameter (similarly to its StartTask sibling), but it also takes parameters for a full key-value pair:
Call StartTask_KeyValue('fbf645f0-0c92-40a4-af9a-6e3eb1d3c35c', 'MyNamespace', 'An important key', 'The value', 3000)
The parameters are
The namespace to store the key-value pair in (required).
The key (required).
The value (required).
An time-to-live valud in milliseconds (optional). When the ttl times out the key-value pair is automatically deleted.
Documentation about Butler’s key-value store is available here.
An example showing how task chaining with parameters can be done using key-values is found here.
Start several tasks using task IDs
If several tasks should be started using task IDs, those IDs need to be passed into the StartTask sub.
This is done by storing the task IDs in a separate table whose name is passed as a parameter into StartTask:
These tables can be called anything as long as
They are qualified (i.e. keep the “Qualify *;” statement!).
The table names are passed as parameters to the StartTask function.
The table MUST have a field called TaskId that contains the IDs of reload tasks to be started.
Regarding parameters to StartTask:
Trailing, unused parameters can be omitted.
Unused parameters that are followed by used parameters should be set to Null().
Example 1
The script below will start tasks fbf645f0-0c92-40a4-af9a-6e3eb1d3c35c (via the first parameter), 7552d9fc-d1bb-4975-9a38-18357de531ea (via second parameter, i.e. a table) and fb0f317d-da91-4b86-aafa-0174ae1e8c8f (via second parameter too).
Similar to how multiple tasks can be started using a table of task IDs (see above), tasks can also be started using a table containing custom property names and values.
Example 1
The script below will start all reload tasks that have the taskGroup custom property set to a value of tasks1.
Butler can be configured to listen to a specific MQTT topic (specified in config file property Butler.mqttConfig.taskStartTopic) and use any message received in that topic as a Sense task ID, which is then started.
For example:
A Sense app, used by end users, relies on data in a source system that talks MQTT (there are lots of MQTT libraries available, covering most operating systems).
The data in the source system can be updated at any time.
In order to update the Sense app with data the most common approach is to schedule reloads of the Qlik Sense app at certain intervals, i.e. polling the source system.
But if the source system instead posts a MQTT message on a well defined topic when new data is available, theat message will trigger the Sense app’s reload.
This way the Sense app will be updated as quickly as possible after new data is availabe in the source system.
I.e. the end user will have access to more up-to-date data, compared to the polling based solution.
Requirements for starting tasks via MQTT
These config file settings must be set up before Butler will use MQTT messages to start tasks:
Connection to MQTT broker (=server):
Butler.mqttConfig.enable: true
Butler.mqttConfig.brokerHost:
Butler.mqttConfig.brokerPort:
MQTT topics that Butler should subscribe to
Butler.mqttConfig.subscriptionRootTopic: <Root topic that Butler should subscribe to. Something like qliksense/#>
Butler.mqttConfig.taskStartTopic: <Topic used to start Sense tasks. MUST be a suptopic to the root topic above!>
For security reasons Qlik Sense does not offer direct access to the file system from load scripts. Using lib:// constructs files can be read and written, but not copied, moved or deleted.
Butler has APIs that enabled file copy/move/delete in a secure, controlled way.
Goal: Copy, move and delete files from Sense load scripts
These steps are needed to achieve the goal:
Install and configure Butler’s general settings.
Add the directories in which file operations should be allowed to Butler’s config file.
Make sure the account Butler runs under has the appropriate access to those directories.
Call the Butler APIs directly or use the subs included in the GitHub repo to do the desired file operations.
Warning: UNC paths only on Windows
UNC paths (i.e. “\\host\fileshare\folder1\folder2”) is a Windows-only feature and as such only supported when Butler is running on Windows.
If Butler is running on a non-Windows operating system and directories on network file shares should be accessible via Butler’s RESR API, those directories must be mounted on the server using the standard OS mechanisms, then accessed via the server’s local file system.
Butler will warn in the console and file logs if UNC paths are specified in the config file, and Butler is NOT running on Windows.
The general idea is:
For each file system operation (copy, move and delete) you can specify in which (or between which) directories that operation should be allowed.
This is straight forward, but because Butler can run on different operating systems AND access file shares hosted by various OSs, things can get a bit complicated.
In most cases the paths to use are the expected ones, but when it comes to UNC paths they can for example either use forward slash “/” or back ditto “\”.
Both work as all paths are normalized into an internal, uniform format when loaded into Butler.
A few examples show how to deal with some common scenarios:
fileCopyApprovedDirectories:- fromDirectory:/data1/qvd # Butler running on Linux, with either a local directory in /data1, or a remote fileshare mounted into /data1toDirectory:/data2/qvd_archive- fromDirectory:e:\data3\qvd # Butler running on Windows Server, accessing files/directories in the local file systemtoDirectory:e:\data4\qvd_archive- fromDirectory://server1.my.domain/fileshare1/data1 # Butler running on Windows server, accessing a SMB file share (which can be on a Windows or Linux server)toDirectory://server1.my.domain/fileshare1/data2- fromDirectory:\\server1.my.domain\fileshare1\data1toDirectory:\\server1.my.domain\fileshare1\data2fileMoveApprovedDirectories:- fromDirectory:/data7/qvdtoDirectory:/data8/qvd_archive- fromDirectory:e:\data9\qvdtoDirectory:e:\data10\qvd_archive- fromDirectory://server2.my.domain/data1/qvdtoDirectory://server2.my.domain/data1/qvd_archivefileDeleteApprovedDirectories:- /data1/qvd_archive- e:\data1\qvd_archive- //server3.my.domain/data1/qvd_archive- \\server3.my.domain\data1\qvd_archive
This configuration (for example) means:
Copying can be done from e:\data3\qvd to e:\data4\qvd_archive, but not from e:\data3\qvd to e:\data6\qvd_archive
Moving files can be done from /data7/qvd to /data8/qvd_archive, but not from /data7/qvd to e:\data9\qvd
Files can be deleted in the directories /data1/qvd_archive, e:\data1\qvd_archive and (using UNC notation) \\server3.my.domain\data1\qvd_archive.
3. Create Sense data connections used to call Butler’s REST API
Once you know what file path format to use (see above), using the helper subs is pretty easy:
// Where is Butler running?
let vButlerHost = 'http://<IP_ADDRESS>';
let vButlerPort = 8080;
// Delete files
Call DeleteFile('/data1/qvd_archive/a.txt')
Call DeleteFile('e:\data1\qvd_archive\a.txt')
Call DeleteFile('//server3.my.domain/data1/qvd_archive\a.txt')
// Copy files with options overwrite-if-exists=true and keep-source-timestamp=true
Call CopyFile('/data1/qvd/a.txt', '/data2/qvd_archive/a.txt', 'true', 'true')
Call CopyFile('e:\data5\qvd\a.txt', 'e:\data6\qvd_archive\a.txt', 'true', 'true')
// Move files with option overwrite-if-exists=true
Call MoveFile('/data7/qvd/a.txt', '/data8/qvd_archive/a.txt', 'true')
Call MoveFile('e:\data9\qvd\a.txt', 'e:\data10\qvd_archive\a.txt', 'true')
If you prefer to call the REST API directly, the DeleteFile sub might provide some inspiration:
// ------------------------------------------------------------
// ** Delete file **
//
// Files can only be deleted in folders (and subfolders of) directories that
// have been approved in the Butler config file.
//
// Paramaters:
// vFile : File to be deleted.
// ------------------------------------------------------------
sub DeleteFile(vFile)
let vFile = Replace('$(vFile)', '\', '/');
let vFile = Replace('$(vFile)', '#', '%23');
let vRequestBody = '{""deleteFile"":""$(vFile)""}';
LIB CONNECT TO 'Butler_POST';
RestConnectorMasterTable:
SQL SELECT
"vFile"
FROM JSON (wrap on) "root"
WITH CONNECTION (
Url "$(vButlerHost):$(vButlerPort)/v4/filedelete",
BODY "$(vRequestBody)",
HTTPHEADER "X-HTTP-Method-Override" "DELETE"
);
set vFile=;
set vRequestBody=;
DROP TABLE RestConnectorMasterTable;
end sub
Note how the HTTP operation is set using the X-HTTP-Method-Override HTTP header.
This is a way to work around a limitation of Qlik’s REST connector, as it only supports GET and POST operations. The extra HTTP header tells Butler what kind of HTTP operation should really be carried out.
Examples using UNC paths
When specifying UNC paths in the Butler config file and running Butler on a non-Windows operating system, you will get warnings like the ones below.
The approved directories sections of the config file look like this:
Butler:....# List of directories between which file copying via the REST API can be done.fileCopyApprovedDirectories:- fromDirectory:/from/some/directory2toDirectory:/to/some/directory2- fromDirectory://<IP_ADDRESS>/qlik/testdata/deletefile1toDirectory://<IP_ADDRESS>/qlik/testdata/deletefil2# List of directories between which file moves via the REST API can be done.fileMoveApprovedDirectories:- fromDirectory:/from/some/directory3toDirectory:/to/some/directory3- fromDirectory://<IP_ADDRESS>/qlik/testdata/deletefile1toDirectory://<IP_ADDRESS>/qlik/testdata/deletefil2fileDeleteApprovedDirectories:- /from/some/directory2- \\<IP_ADDRESS>\qlik\testdata\deletefile3
In this case Butler is running on macOS (with IP <IP_ADDRESS> on port 8081) and we get warnings in the logs when starting Butler:
When trying to do a file operation (in this case a delete) using an UNC path (Butler is still running on macOS!) we get a warning in the logs and a http error returned to the Sense script:
7 - Sense apps that explain and highlight various Butler features
Butler comes with several demo apps.
Feel free to review them to get a better understanding of how Butler can be used.
7.1 - Using Butler APIs from Sense load script
This app uses the helper subs call some of Butler’s APIs. It’s not diving too deep into any particular feature, but rather just calls most APIs to show how it’s done.
If unsure what the parameters of the helper subs should look like, this page might be useful.
Calling the Butler API from Sense app’s load script
The demo app Butler 5.0 - demo app.qvf is available in the GitHub repository.
The app includes examples on how to use many of Butler’s REST APIs endpoints.
It doesn’t have much of a user interface (it just shows what API endpoints are enabled) so you should look at the load script to get examples of how to use the Butler APIs.
The app includes a copy of the helper functions that are also available in the GitHub repository.
7.2 - Partial loads in Qlik Sense
It’s surprisingly difficult to do partial loads in Qlik Sense Enterprise on Windows.
In QlikView that feature was easily available, but in QSEoW it’s currently not possible to create reload tasks that do partial app reloads.
Butler has an API for doing partial reloads of apps. A couple of demo apps are also includedin the GitHub repository.
Partial reload API
The full API documentation is available in the Reference section, here we’re interested in the PUT /v4/app/{appId}/reload endpoint.
Demo app showing how to post message to Slack from Qlik Sense load script.
Load script
Assuming the .qvs helper subs are used, only one line of script is needed to send a Slack message:
// -------------------------------------------
// Post messsage to Slack
// -------------------------------------------
// Post a basic message to Slack
Call PostToSlack('#general', 'Butler the Bot', '👽 Greetings, we come in peace.' , ':ghost:')
Note how emojis can be used in the message and a message specific icon can be used (":ghost:" above).
Demo app showing how to publish message to MQTT from Qlik Sense load script.
Load script
Assuming the .qvs helper subs are used, only one line of script is needed to publish a MQTT message.
The demo app does a bit more. First it posts a startup message to MQTT, then it loads some data and finally an all-done message is sent:
// -------------------------------------------
// Publish a MQTT message, load some data and publish another message
Call PostToMQTT('butler/5.0/demo-reloading/status', 'reload started')
// Load some data
Characters:
Load Chr(RecNo()+Ord('A')-1) as Alpha, RecNo() as Num autogenerate 26;
// Publish final message
Call PostToMQTT('butler/5.0/demo-reloading/status', 'reload done')
The MQTT messages look like this in the MQTT Explorer app on mac OS:
If running Butler on a Windows computer it is possible to install Butler as a Windows service.
This means that Butler will start automatically when the computer starts, and will run in the background without any user interaction.
A blog post on ptarmiganlabs.com goes through the steps required to install Butler SOS as a Windows service, the steps needed for Butler are virtually identical.


laravel
A command-line installer for the Laravel framework.
More information: home page
- Create a new Laravel application:
laravel new name
- Use the latest development release:
laravel new name --dev
- Overwrite if the directory already exists:
laravel new name --force
- Install the Laravel Jetstream scaffolding:
laravel new name --jet
- Install the Laravel Jetstream scaffolding with a specific stack:
laravel new name --jet --stack livewire|inertia
- Install the Laravel Jetstream scaffolding with support for teams:
laravel new name --jet --teams
- List the available installer commands:
laravel list


"These principles expose the dependency management aspects of OOD as opposed to the conceptualization and modeling aspects. This is not to say that OO is a poor tool for conceptualization of the problem space, or that it is not a good venue for creating models."
by Uncle Bob.
Clean code description here.
XP Programming description here.
I've being involved in great projects for different markets:
My main roles are as expert software developer applying software architecture, analysis, development, tech lead for big and small teams, tech coach and programming core, functional or infrastructural parts of the many applications.
Contact meMy expertise is based on .Net based solutions. I'm continous increasing my expertise on:
Node JS entusiast


+
%
User satisfaction
+
%
Popularity
+
%
New users
+
%
Visits
+
%
Income
+
%
Sales
Site Statistics
Weekly Stat
- Visits: 356
- Unique Visitors: 252
- Pageviews: 781
- Pages / Visit: 2,19
- Avg. Visit Duration: 00:02:58
- Bounce Rate: 59,83%
- % New Visits: 70,79%
- % Returning Visitor: 29,21%
Server Load
Tasks in Progress
iOS App Development 20
Android App Development 40
A/B Tests 60
Server Load Tests 80
Django Backend Development 100
Users
7Comments
4Orders
Products
Messages
Calendar
8Projects
Likes
+ 11Favorites
Notifications
7Settings
Dashboard
Calendar
Support tickets
- Server unavaible [ #199278 ] Ashley Tan [ Low priority ] Status: [ Complete ] Jul 25, 2012 11:09
- Mobile App Problem [ #199277 ] Ann Kovalsky [ Normal priority ] Status: [ Pending ] Jul 25, 2012 11:09
- PayPal issue [ #199276 ] Chris Dan [ High priority ] Status: [ In progress ] Jul 25, 2012 11:09
- IE7 problem [ #199275 ] John Grand [ Low priority ] Status: [ Rejected ] Jul 25, 2012 11:09
- Server unavaible [ #199274 ] Agnes Young [ Low priority ] Status: [ Complete ] Jul 25, 2012 11:09
- Mobile App Problem [ #199273 ] Melanie Brown [ Normal priority ] Status: [ Pending ] Jul 25, 2012 11:09
- PayPal issue [ #199272 ] Patricia Doyle [ High priority ] Status: [ In progress ] Jul 25, 2012 11:09
Weekly Stat
Last Users
-
Name: Łukasz Holeczek
Since: Jul 25, 2012 11:09
Status: Approved -
Name: Bill Cole
Since: Jul 25, 2012 11:09
Status: Pending -
Name: Jane Sanchez
Since: Jul 25, 2012 11:09
Status: Banned -
Name: Kate Presley
Since: Jul 25, 2012 11:09
Status: Updates


DSCensor
Data Aggregation, Visualization and Retrieval
Home
Query Builder
Views
Assembly
Annotation
Submit
Help
About
Links


Előételek
Some quick example text to build on the card title and make up the bulk of the card's content.
RendelésFőételek
Some quick example text to build on the card title and make up the bulk of the card's content.
RendelésDesszertek
Some quick example text to build on the card title and make up the bulk of the card's content.
Rendelés


Mutual Fund Investment Calculator
SIP
LumpSum
Currency
₹ INR
💰USD
Monthly Investment ❓
Number of Years ❓
Expected Rate of Return ❓
Calculate
Result :
Monthly Investment for
SIP
Rs.
Number of Years
SIP
Years:
Expected Rate of Return
SIP
%:
Total Investment 💸
Rs.
Wealth Gained 💸
Rs.
Maturity Value 💸
Rs.


Before Change
return ValueError()
// Append undirected edges.
edges = torch.cat((edges, edges.index_select(1, torch.LongTensor([1, 0]))))
// Sort the adjacencies row-wise.
edges = edges.t()
After Change
// Build directed adjacency matrix.
adj = torch.sparse.FloatTensor(edges.t(),
torch.ones(edges.size(0)),
torch.Size([n, n]))
// Convert to undirected adjacency matrix.
adj = adj + adj.t()
// Remove duplicate indices.
// NOTE: This doesn"t work if transpose(...) is removed.
adj = adj.transpose(0, 1).coalesce()


--- layout: post title: How to check which terminals are supported in *nix? tags: - unix - terminals - linux ---
Recently I needed to know which terminal I could set my $TERM variable to in tmux’s configuration file so I stumbled across this little nugget o’ knowledge.
grep ‘^[a-zA-Z]’ /etc/termcap | more


|
Drake
|
Represents models for a sequence of AbstractValues (usually a sequence of either input or output ports). More...
#include <drake/systems/framework/model_values.h>
Public Member Functions | |
| ModelValues ()=default | |
| int | size () const |
| Returns one greater than the largest index passed to AddModel or AddVectorModel. More... | |
| void | AddModel (int index, std::unique_ptr< AbstractValue > model_value) |
Sets model_value to be the model value for index . More... | |
| template<typename T > | |
| void | AddVectorModel (int index, std::unique_ptr< BasicVector< T >> model_vector) |
Wraps model_vector in a Value and sets that to be the model value for index . More... | |
| std::unique_ptr< AbstractValue > | CloneModel (int index) const |
Returns a clone of the model value at index , which may be nullptr. More... | |
| std::vector< std::unique_ptr< AbstractValue > > | CloneAllModels () const |
| Returns a vector of all the cloned model values. Some may be nullptr. More... | |
| template<typename T > | |
| std::unique_ptr< BasicVector< T > > | CloneVectorModel (int index) const |
Returns a clone of the vector within the model value at index , which may be nullptr. More... | |
Does not allow copy, move, or assignment | |
| ModelValues (const ModelValues &)=delete | |
| ModelValues & | operator= (const ModelValues &)=delete |
| ModelValues (ModelValues &&)=delete | |
| ModelValues & | operator= (ModelValues &&)=delete |
Represents models for a sequence of AbstractValues (usually a sequence of either input or output ports).
The models are the "prototype" design pattern (https://en.wikipedia.org/wiki/Prototype_pattern). When creating elements in new Context, these models' values are cloned to establish the subtype and default values of the, e.g. input port.
Conceptually, the ModelValues form an infinite sequence. The value at a given index is allowed to be absent, in which case the CloneModel method will return nullptr. Adding new values must be monotonic; new values must use strictly larger indices; the model value for a given index cannot be reset.
|
delete |
|
delete |
|
default |
| void AddModel | ( | int | index, |
| std::unique_ptr< AbstractValue > | model_value | ||
| ) |
Sets model_value
to be the model value for index
.
| void AddVectorModel | ( | int | index, |
| std::unique_ptr< BasicVector< T >> | model_vector | ||
| ) |
|
inline |
Returns a vector of all the cloned model values. Some may be nullptr.
| std::unique_ptr< AbstractValue > CloneModel | ( | int | index | ) | const |
Returns a clone of the model value at index
, which may be nullptr.
| std::unique_ptr< BasicVector< T > > CloneVectorModel | ( | int | index | ) | const |
Returns a clone of the vector within the model value at index
, which may be nullptr.
| std::exception | if the index has a model but the model's type does not match the given T |
|
delete |
|
delete |
| int size | ( | ) | const |
Returns one greater than the largest index passed to AddModel or AddVectorModel.


yes it overlaps with #177 @jdmarlow86
i've added filtering in quick search field
if you type in 'spv' or 'eth' you'll see all spv or all eth/erc20 coins
it's not intuitive though
`11127ab` adds heir doc to sidebar - gcharang
`8f36bdf` edited through the introduction of the heir doc - gcharang
`15244f9` Fixes #26 - gcharang
`52dacb7` Merge branch 'dev' into gcharang - gcharang
`6a64477` minor edits and edited through heirfund section... - gcharang
`667b55e` Merge pull request #29 from KomodoPlatform/gcha... - siddhartha-crypto
`a35077c` updates primarily to CC Heir, and some other st... - siddhartha-crypto
`f1a6397` manually correcting [] leftovers - siddhartha-crypto
`c270fa7` rapid spot check over all documentation - siddhartha-crypto
`4568f96` first attempt at accounting for the new ac_stak... - siddhartha-crypto


This task will guide you through the process of converting an existing Win32 desktop app to a Desktop Bridge UWP app using Visual Studio 2017. There are a lot of steps to correctly set up Visual Studio 2017 to build and package your Win32 app as a UWP app. Each update of Visual Studio 2017 had made this process easier. Future updates to Visual Studio 2017 will most likely add Desktop Bridge project templates that will automate this process. Until then, please follow these steps carefully.
Basic knowledge of C# development
Basic knowledge of client development with the .NET framework
Basic knowledge of Windows 10 and the Universal Windows Platform
A computer with Windows 10 Anniversary Update or Windows 10 Creators Update. If you want to use the Desktop App Converter with an installer, your PC must be running Windows 10 Pro or Windows 10 Enterprise (Windows 10 Home doesn't include the required Containers feature).
Visual Studio 2017 with the tools to develop applications for the Universal Windows Platform. Any edition of Visual Studio 2017 is supported, including the free Visual Studio 2017 Community
Go to the Git repo at https://github.com/Knowzy/KnowzyInternalApps and clone or download the content onto your local computer.
This task covers the following steps:
Open the existing Knowzy Win32 solution with Visual Studio 2017
Add a UWP project and add a project dependency to the existing WPF project
Add the Microsoft.Knowzy.WPF binaries to the UWP project
Edit the Microsoft.Knowzy.UWP package manifest to enable the Desktop Bridge extensions
Deploy and run your converted Win32 App
We will be converting an existing WPF application from Win32 to UWP. To get started, use Visual Studio 2017 to open Microsoft.Knowzy.WPF.sln in the src\Knowzy_Engineering_Win32App folder.
Set the Microsoft.Knowzy.WPF project as the startup project. Press F5 to build and run the project. Feel free to try out the application and then quit the application and return to Visual Studio.
We will be using an empty UWP Visual Studio project to package our WPF app into a UWP app.
To create a Desktop Bridge package, first add a C# Windows Universal Blank App project to the your solution.
In Solution Explorer, right-click the src folder and select Add | New Project...
In the left pane of the Add New Project window, select the Visual C# | Windows Universal | Blank App (Universal Windows) project template.
In the Name box, enter Microsoft.Knowzy.UWP.
In the Location box, verify that you're saving the project to the Knowzy_Engineering_Win32App\src folder, and then click OK.
In the New Universal Windows Project window, verify that Minimum Version is set to Windows 10 Anniversary Update (10.0; Build 14393) or higher.
Note: Desktop Bridge apps require Windows 10 SDK 14393 or higher. If you only have the Windows 10 SDK 15063 installed on your PC, use Windows 10 Creators Update (10.0; Build 15063) for the Minimum Version. You don't need to install the Windows 10 SDK 14393 to complete these tasks.
Your solution should now contain the following projects.
Add a project dependency to Microsoft.Knowzy.WPF
In Solution Explorer, right-click the Microsoft.Knowzy.UWP (Universal Windows) project.
Select Build Dependencies | Project Dependencies..."
In the Depends on section of the Project Dependencies window, select the Microsoft.Knowzy.WPF check box, and then click OK.
Press F7 (or whatever your Build Solution shortcut key is) to build the solution.
To see what the empty C# UWP app looks like
In Solution Explorer, right-click the Microsoft.Knowzy.UWP (Universal Windows) project and select Debug | Start new instance to run the UWP app.
An empty UWP app window will appear.
Close the window to return to Visual Studio 2017.
To convert the Microsoft.Knowzy.WPF app to a Desktop Bridge UWP app, you will need to add all the Win32 binaries created by the Microsoft.Knowzy.WPF app to the Microsoft.Knowzy.UWP app. You will copy them to a folder called desktop (this exact name is not required; you can use any name you like), and then package them with the UWP app.
We will automate the Microsoft.Knowzy.WPF project to copy these files after each build, improving the development workflow. We are going to edit the project file Microsoft.Knowzy.WPF.csproj to include an AfterBuild target that will copy all the Win32 output files to the desktop folder in the Microsoft.Knowzy.UWP project as follows:
<Target Name="AfterBuild">
<PropertyGroup>
<TargetUWP>..\Microsoft.Knowzy.UWP\desktop\</TargetUWP>
</PropertyGroup>
<ItemGroup>
<DesktopBinaries Include="$(TargetDir)\**\*.*" />
<ExcludeFilters Include="$(TargetDir)\**\*.winmd" />
</ItemGroup>
<ItemGroup>
<DesktopBinaries Include="$(TargetDir)\**\*.*" />
</ItemGroup>
<ItemGroup>
<DesktopBinaries Remove="@(ExcludeFilters)" />
</ItemGroup>
<Copy SourceFiles="@(DesktopBinaries)" DestinationFiles="@(DesktopBinaries->'$(TargetUWP)\%(RecursiveDir)%(Filename)%(Extension)')" />
</Target>
This rather complicated bit of XML completes several important tasks:
The TargetUWP line specifies where to copy the Win32 binaries. In this example, the binaries will be copied to the desktop folder in the Microsoft.Knowzy.UWP project folder.
The ExcludeFilters line specifies that any .winmd files in the Microsoft.Knowzy.WPF output folder will not be copied to the output directory.
The DesktopBinaries lines specify that all of the DLL dependencies of the Microsoft.Knowzy.WPF EXE (including the ones from the NuGet packages) will be copied to the output directory.
The Copy SourceFiles line specifies that the directory structure will be preserved when the files are copied.
To automate copying the WPF binaries, edit the XML of the Microsoft.Knowzy.WPF.csproj
In Visual Studio, right-click the Microsoft.Knowzy.WPF project and select Unload project.
Right-click the Microsoft.Knowzy.WPF project and select Edit Microsoft.Knowzy.WPF.csproj.
Scroll to the end of the XML file and paste the above XML code to the end of the file before the final project tag.
Save your changes and then reload Microsoft.Knowzy.WPF.
Rebuild the solution so the Microsoft.Knowzy.WPF project binaries will be copied to the Microsoft.Knowzy.UWP/desktop folder.
Now that the Win32 binaries are copied to the desktop folder in the Microsoft.Knowzy.UWP project after the build, we need to add the binaries to the UWP project so they will be packaged with the UWP app.
We will automate this process, similar to how we automated copying the files, as follows:
<ItemGroup>
<Content Include="desktop\**\*.*">
<Link>desktop\%(RecursiveDir)%(FileName)%(Extension)</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
This segment of XML completes several important tasks:
The Content Include line specifies that all of the files in the desktop folder will be packaged with the UWP app
The Link line specifies that the files will be copied to the AppX, preserving their directory structure
To automate adding the WPF binaries to the UWP project, edit the XML of the Microsoft.Knowzy.UWP.csproj
In Visual Studio, right-click the Microsoft.Knowzy.UWP project and select Unload project.
Right-click the Microsoft.Knowzy.UWP project and select Edit Microsoft.Knowzy.UWP.csproj.
Scroll to the end of the XML file and paste the above XML code to the end of the file before the final project tag.
Save your changes and then reload Microsoft.Knowzy.UWP.
Rebuild the solution so the Microsoft.Knowzy.WPF project binaries will be added to the UWP project and packaged with the UWP app.
Verify that the src\Microsoft.Knowzy.UWP folder contains a desktop folder. If the folder is missing, close and reopen Microsoft.Knowzy.WPF.sln.
You should be able to run the src\Microsoft.Knowzy.UWP\desktop\Microsoft.Knowzy.WPF.exe app by navigating to the folder and double-clicking Microsoft.Knowzy.WPF.exe. This will test that all of the dependencies for Microsoft.Knowzy.WPF.exe were copied correctly to the desktop folder.
The Microsoft.Knowzy.UWP project contains a file called Package.appxmanifest that describes how to package your UWP app and its dependencies for the Windows Store.
The package manifest is an XML document that contains the info the system needs to deploy, display, or update a Windows app. This info includes package identity, package dependencies, required capabilities, visual elements, and extensibility points. Every UWP app package must include one package manifest.
We need to edit this file so it includes the information needed to run our Win32 WPF app as a UWP app.
To edit the Package.appxmanifest XML file, right-click the file in the Microsoft.Knowzy.UWP project, and then select View Code.
We will now edit the XML to add the Desktop Bridge extensions. This will enable your Win32 app to run as a UWP app.
Replace the line (near line 7):
IgnorableNamespaces="uap mp">
with
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
xmlns:desktop="http://schemas.microsoft.com/appx/manifest/desktop/windows10"
xmlns:uap4="http://schemas.microsoft.com/appx/manifest/uap/windows10/4"
IgnorableNamespaces="uap mp rescap desktop">
Adding these namespaces will allow us to add the Desktop Bridge extensions to our app.
We need to describe to Windows 10 that our app is a Desktop Bridge app. We also need to specify a minimum version of 13493. Replace the line (near line 25):
<TargetDeviceFamily Name="Windows.Universal" MinVersion="<IP_ADDRESS>" MaxVersionTested="<IP_ADDRESS>" />
with
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.14393.0" MaxVersionTested="10.0.14393.0" />
We need to tell Windows 10 that our app is a Desktop Bridge app and needs to run as a Full Trust application. This capability grants Desktop app capabilities to our UWP app. Add the following capability to the Capabilities section (near line 49)
<rescap:Capability Name="runFullTrust" />
We also need to specify that we are a Full Trust application in the Application tag. This tag also points to our WPF EXE as executable for out app.
Modify the Application tag to the following (near line 34):
<Application Id="Knowzy" Executable="desktop\Microsoft.Knowzy.WPF.exe" EntryPoint="Windows.FullTrustApplication">
Your package.appxmanifest should now look something like:
<?xml version="1.0" encoding="utf-8"?>
<Package
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
xmlns:desktop="http://schemas.microsoft.com/appx/manifest/desktop/windows10"
xmlns:uap4="http://schemas.microsoft.com/appx/manifest/uap/windows10/4"
IgnorableNamespaces="uap mp rescap desktop">
<Identity
Name="9aed127a-4cd4-4b87-a6a6-4b63499a73cb"
Publisher="CN=stammen"
Version="<IP_ADDRESS>" />
<mp:PhoneIdentity PhoneProductId="9aed127a-4cd4-4b87-a6a6-4b63499a73cb" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>
<Properties>
<DisplayName>Microsoft.Knowzy.UWP</DisplayName>
<PublisherDisplayName>stammen</PublisherDisplayName>
<Logo>Assets\StoreLogo.png</Logo>
</Properties>
<Dependencies>
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.14393.0" MaxVersionTested="10.0.14393.0" />
</Dependencies>
<Resources>
<Resource Language="x-generate"/>
</Resources>
<Applications>
<Application Id="Knowzy" Executable="desktop\Microsoft.Knowzy.WPF.exe" EntryPoint="Windows.FullTrustApplication">
<uap:VisualElements
DisplayName="Microsoft.Knowzy.UWP"
Square150x150Logo="Assets\Square150x150Logo.png"
Square44x44Logo="Assets\Square44x44Logo.png"
Description="Microsoft.Knowzy.UWP"
BackgroundColor="transparent">
<uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png"/>
<uap:SplashScreen Image="Assets\SplashScreen.png" />
</uap:VisualElements>
</Application>
</Applications>
<Capabilities>
<Capability Name="internetClient" />
<rescap:Capability Name="runFullTrust" />
</Capabilities>
</Package>
Note: Your Publisher, PublisherDisplayName, and other app id properties will be different.
Your converted Win32 app is now ready to be deployed and run as a UWP app on your computer.
Note: If your Solution configuration is Debug | Any CPU, you will need to enable both the Build and Deploy setting of the Microsoft.Knowzy.UWP app using the Configuration Manager.
Make sure that the Build and Deploy check boxes are selected for the Microsoft.Knowzy.UWP project.
If you try to deploy at this point, you will see an error that says Applications with custom entry point executables are not supported. Check Executable attribute of the Application element in the package manifest
:
1>------ Build started: Project: Microsoft.Knowzy.UWP, Configuration: Debug x86 ------
1> Microsoft.Knowzy.UWP -> C:\Users\stammen\github\BuildTourHack\src\Microsoft.Knowzy.UWP\bin\x86\Debug\Microsoft.Knowzy.UWP.exe
1>C:\Program Files (x86)\MSBuild\15.0\.Net\CoreRuntime\Microsoft.Net.CoreRuntime.targets(236,5): error : Applications with custom entry point executables are not supported. Check Executable attribute of the Application element in the package manifest
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
========== Deploy: 0 succeeded, 0 failed, 0 skipped ==========
Unfortunately there is a bug in the current version of Visual Studio 2017 that prevents Debug builds of C# Desktop Bridge apps from being deployed. This bug will be fixed in a future update to Visual Studio 2017. Until the bug is fixed, we will need to use the Release configuration for our C# Desktop Bridge app. We will use the *Build | Configuration Manager to set this up.
For the Microsoft.Knowzy.UWP project, set the Configuration to Release. You should also do this for the x86 and x64 Platform builds.
Right-click the Microsoft.Knowzy.UWP project and select Deploy from the menu.
2>------ Deploy started: Project: Microsoft.Knowzy.UWP, Configuration: Release x86 ------
2>Creating a new clean layout...
2>Copying files: Total 11 mb to layout...
2>Checking whether required frameworks are installed...
2>Registering the application to run from layout...
2>Deployment complete (0:00:01.818). Full package name: "9aed127a-4cd4-4b87-a6a6-4b63499a73cb_<IP_ADDRESS>_x86__71pt5m19pd38p"
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========
========== Deploy: 1 succeeded, 0 failed, 0 skipped ==========
Your Win32 WPF app has now been packaged as a UWP app using Visual Studio.
In the Windows Start menu, search for Microsoft.Knowzy.UWP. If you click the UWP app in the Start menu, you'll notice that it does not run. Actually, it did run but it exited immediately due to an error.
The error is the app cannot load the project.json file it needs to generate the Products list. The app then throws an exception and exits.
We'll debug this error in a later task, but for now, let's comment out some code so that the app will run.
Go to the OnViewAttached() method at line 70 and comment out lines 72-75 statement after base.OnActivate();
protected override void OnViewAttached(object view, object context)
{
/*
foreach (var item in _dataProvider.GetData())
{
DevelopmentItems.Add(new ItemViewModel(item, _eventAggregator));
}
*/
base.OnViewAttached(view, context);
}
Select Rebuild Solution from the Build menu.
Right-click the Microsoft.Knowzy.UWP project and select Deploy from the menu.
In the Windows Start menu, search for Microsoft.Knowzy.UWP. Click Microsoft.Knowzy.UWP to launch your app.
The Microsoft.Knowzy.UWP app should now run with the hacked code.
To fix the error with the project.json file that causes the UWP app to crash, you need to be able to debug the various Knowzy projects. Let's try to debug the Microsoft.Knowzy.UWP project.
We will fix this error and enable the debugging of our app in the next task.


Based on Marathon, Jalian Systems provides a commercial version with extra features and support. You can use MarathonITE and reduce the effort required for creating resilient test suites. Use the included extract method refactoring to reuse your test scripts. Perform exploratory or semi-automatic testing through MarathonITE and share the test scripts with the development team.
While recording test scripts Marathon creates object map entries. Each entry has a name and corresponding recognition properties. Marathon uses object map configuration to identify the recognition properties and name a component. The object map configuration is stored in a YAML formatted text file - omap-configuration.yaml in the project folder. This file can be modified using any text editor.
MarathonITE includes a configuration editor for the omap-configuration.yaml file. This reduces the chances of inadvertently corrupting the file.
More info:
Learn more about MarathonITE


Native Windows GUI: Limitations
Even though NWG wraps a very large amount of Windows functionalities, it is still a very old API.
As such there are a certain kind of applications that cannot be developed with NWG (at least for now).
Win32
NWG use Win32 under the hood. Win32 is a very old API and it only supports Windows PC. Also Win32 does not support touch/pen inputs.
Fancy looking applications
NWG will probably never reach the level of customization a HTML/CSS application can provide. There's a few reason for that.
NWG controls cannot be customized. There is a theme API, but the documentation in very sparse, and it probably wont be implemented in NWG core.
NWG does not have a drawing API. Originally, NWG would have a built-in canvas control that wrapped Direct2D, but the implementation was removed
from the library because it would take too much time to implement.
Transparency is not supported. NWG controls with transparency flickers ALOT. It's almost a health hazard for people with epilepsy.
One way to get rid of this flaw is to outright remove transparency between controls.
NWG has limited support for resource types. NWG can load fonts and the most common images format, but it lacks the ability to play music and videos.
Those features will never be in the core. They should be implemented as external libraries.
NWG do not come with plotting controls or any kind of 3D api. Those will have to be implemented after canvas.
Data efficiency
The way NWG collection controls allocate data is very inefficient. NWG both allocate space to hold the rust specific data and the visible string value of the control.
This means that if your application must log hundread of thousand of items, it will have a hard time.
This can be fixed by implementing OWNDER_DATA
over the controls, but this will take alot of efforts and it will be implemented as
an external library.


I’m a front end developer with a designer’s eye. My background in art and design allows me to see the beauty in just about anything - including all things technology. In college, I took an intro to web development class and got bit by the CSS bug! After graduating with my Associates of Applied Sciences in Digital Art & Design, I decided to take my creative skills to the next level by becoming a front-end web developer. I take pride in my eye for cohesive color schemes and clean designs for any project that comes my way. When I’m not coding, I love cooking, queer media and trying not to die in the mines of Stardew Valley. My Resume
about emmy jordan
I am interested in coding responsive designs for customer-focused services such as entertainment apps & venues, restaurants, and online retail. I would especially love to work on projects that focus on diversity & inclusion of minority & LGBTQIA+ individuals in the media and service industries. As a marginalized individual, I understand the needs of under represented groups, and my goal is to help provide a voice for those people.
My skills
- CSS3
- Git
- HTML5
- JavaScript
- jQuery
- SASS
- WordPress


{% extends "base.html" %} {% block body %}
You must be logged in with an administrative account to view this page.


Link Suites offers you space for several activities including coperate meetings, celebrations and many more.


#include <DOStmtInput_test.h>
This is a generated data object test class that is used for testing the data object called DOStmtInput.
| Helix::Logic::dev::DOStmtInputTest::DOStmtInputTest |
( |
const DOStmtInputTest & |
c | ) |
|
|
inlineprivate |
Copy constructor is private to prevent use.
| DOStmtInputTest::DOStmtInputTest |
( |
| ) |
|
| DOStmtInputTest::~DOStmtInputTest |
( |
| ) |
|
|
virtual |
Compare two lists of objects to see if they are the same.
Compare two objects to see if they are the same.
| void DOStmtInputTest::deleteByID |
( |
IOConn & |
ioc, |
|
|
xmlNodePtr |
node |
|
) |
| |
This method will use our input XML document to prepare for and test the " + doName + "." + methodName + " method. We will use our list of output xml documents to verify the output of this method. If the list of ourput documents is empty, we will simply ensure that no exceptions are thrown using the given XML input document.
| void DOStmtInputTest::deleteByStmtID |
( |
IOConn & |
ioc, |
|
|
xmlNodePtr |
node |
|
) |
| |
This method will use our input XML document to prepare for and test the " + doName + "." + methodName + " method. We will use our list of output xml documents to verify the output of this method. If the list of ourput documents is empty, we will simply ensure that no exceptions are thrown using the given XML input document.
| void DOStmtInputTest::insert |
( |
IOConn & |
ioc, |
|
|
xmlNodePtr |
node |
|
) |
| |
This method will use our input XML document to prepare for and test the DOStmtInput.insert method. We will use our list of output xml documents to verify the output of this method. If the list of ourput documents is empty, we will simply ensure that no exceptions are thrown using the given XML input document.
Assignment operator is private to prevent use.
| void DOStmtInputTest::runTests |
( |
IOConn & |
ioc, |
|
|
xmlNodePtr |
node |
|
) |
| |
|
virtual |
| void DOStmtInputTest::selectAllForDOStmt |
( |
IOConn & |
ioc, |
|
|
xmlNodePtr |
node |
|
) |
| |
This method will use our input XML document to prepare for and test the DOStmtInput.selectAllForDOStmt method. We will use our list of output xml documents to verify the output of this method. If the list of ourput documents is empty, we will simply ensure that no exceptions are thrown using the given XML input document.
| void DOStmtInputTest::update |
( |
IOConn & |
ioc, |
|
|
xmlNodePtr |
node |
|
) |
| |
This method will use our input XML document to prepare for and test the " + doName + "." + methodName + " method. We will use our list of output xml documents to verify the output of this method. If the list of ourput documents is empty, we will simply ensure that no exceptions are thrown using the given XML input document.
Registers us with the global factory map.
The documentation for this class was generated from the following files:


|
BTK
0.3dev.0
Open-source library to visualize/process biomechanical data
|
Base class for all type of force platform. More...
#include <btkForcePlatform.h>
Public Types | |
| typedef Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic > | CalMatrix |
| typedef AnalogCollection::ConstIterator | ConstIterator |
| typedef SharedPtr< const ForcePlatform > | ConstPointer |
| typedef Eigen::Matrix< double, 3, 1 > | Corner |
| typedef AnalogCollection::Iterator | Iterator |
| typedef Eigen::Matrix< double, 3, 1 > | Origin |
| typedef SharedPtr< ForcePlatform > | Pointer |
| Public Types inherited from btk::DataObject | |
| typedef SharedPtr< const DataObject > | ConstPointer |
| typedef SharedPtr< DataObject > | Pointer |
| Public Types inherited from btk::Object | |
| typedef SharedPtr< const Object > | ConstPointer |
| typedef SharedPtr< Object > | Pointer |
Public Member Functions | |
| Iterator | Begin () |
| ConstIterator | Begin () const |
| Pointer | Clone () const |
| Iterator | End () |
| ConstIterator | End () const |
| CalMatrix & | GetCalMatrix () |
| const CalMatrix & | GetCalMatrix () const |
| Analog::Pointer | GetChannel (int idx) const |
| int | GetChannelNumber () const |
| AnalogCollection::Pointer | GetChannels () const |
| const Corner | GetCorner (int idx) const |
| Corners & | GetCorners () |
| const Corners & | GetCorners () const |
| Origin & | GetOrigin () |
| const Origin & | GetOrigin () const |
| int | GetType () const |
| void | SetCalMatrix (const CalMatrix &cal) |
| void | SetChannel (int idx, Analog::Pointer c) |
| void | SetCorner (int row, int col, double v) |
| void | SetCorner (int idx, double x, double y, double z) |
| void | SetCorner (int idx, const Corner &c) |
| void | SetCorners (const Corners &c) |
| void | SetOrigin (double x, double y, double z) |
| void | SetOrigin (const Origin &o) |
| ~ForcePlatform () | |
| Public Member Functions inherited from btk::DataObject | |
| DataObject * | GetParent () const |
| bool | HasParent () const |
| void | Modified () |
| void | SetParent (DataObject *parent) |
| void | Update () |
| Public Member Functions inherited from btk::Object | |
| unsigned long int | GetTimestamp () const |
Static Public Member Functions | |
| static Pointer | New () |
Public Attributes | |
| EIGEN_MAKE_ALIGNED_OPERATOR_NEW typedef Eigen::Matrix< double, 3, 4 > | Corners |
Protected Member Functions | |
| ForcePlatform () | |
| Protected Member Functions inherited from btk::DataObject | |
| DataObject () | |
| DataObject (const DataObject &toCopy) | |
| virtual | ~DataObject () |
| Protected Member Functions inherited from btk::Object | |
| Object () | |
| Object (const Object &toCopy) | |
| virtual | ~Object () |
Protected Attributes | |
| CalMatrix | m_CalMatrix |
| AnalogCollection::Pointer | m_Channels |
| int | m_Type |
Base class for all type of force platform.
This class is generic and doesn't know its type, nor the number of analog channels used. To use predefined force platform as proposed in the documentation of the C3D file format, check the following classes:
Type which represents a possible calibration matrix used with the force platform.
Const iterator for channels contained in the force platform object.
Smart pointer associated with a const ForcePlatform object.
Type which represents the coordinates of one corner.
Iterator for channels contained in the force platform object.
Type which represents the origin of the force platform.
Smart pointer associated with a ForcePlatform object.
|
inline |
Empty destructor.
|
protected |
Constructor.
|
inline |
Returns an iterator to the beginning of the list of items.
|
inline |
Returns a const iterator to the beginning of the list of items.
|
inline |
Clones the object and return it as new smart pointer.
|
inline |
Returns an iterator just past the last item.
|
inline |
Returns a const iterator just past the last item.
|
inline |
Returns calibration marix.
|
inline |
Returns the calibration matrix.
|
inline |
Returns the channel at the index idx.
|
inline |
Returns the number of channels.
|
inline |
Returns force platform's channels.
| const ForcePlatform::Corner btk::ForcePlatform::GetCorner | ( | int | idx | ) | const |
Returns the corner at index idx.
|
inline |
Returns corners.
|
inline |
Returns corners.
|
inline |
Returns the origin of the force platform.
|
inline |
Returns the origin of the force platform.
|
inline |
Returns the type of the force platform.
|
inlinestatic |
Creates a smart pointer associated with a ForcePlatform object.
| void btk::ForcePlatform::SetCalMatrix | ( | const CalMatrix & | cal | ) |
Set the calibration matrix
| void btk::ForcePlatform::SetChannel | ( | int | idx, |
| Analog::Pointer | c | ||
| ) |
Sets the channel at the index idx by the object c.
| void btk::ForcePlatform::SetCorner | ( | int | row, |
| int | col, | ||
| double | v | ||
| ) |
Sets the coordinate at position row and col with the value v.
| void btk::ForcePlatform::SetCorner | ( | int | idx, |
| double | x, | ||
| double | y, | ||
| double | z | ||
| ) |
Set the coordinates of the corner idx.
| void btk::ForcePlatform::SetCorner | ( | int | idx, |
| const Corner & | c | ||
| ) |
Set the corner idx by c.
| void btk::ForcePlatform::SetCorners | ( | const Corners & | c | ) |
Set corners by c.
| void btk::ForcePlatform::SetOrigin | ( | double | x, |
| double | y, | ||
| double | z | ||
| ) |
Sets the origin.
| void btk::ForcePlatform::SetOrigin | ( | const Origin & | o | ) |
Sets the origin.
| btk::ForcePlatform::Corners |
Type which represents the coordinates of the four corners of the force platform.
|
protected |
Calibrage matrix which could be used to correct cross talk between channels.
|
protected |
Channels of the force platform.
|
protected |
Type of the force platform. Used to determine necessary data for a particular force platform model.


Home
Car Manager
Year:
Make:
or pick a make
Ford
Chevrolet
Kia
Toyota
Model:
Number of Doors
Save
Clear


{% load i18n %}
Login to Yammer and grant Crowy access to your Yammer Account. After 4 digit access code is displayed, enter the code into the text box of No.2.
{% trans "Get access code from Yammer" %}
Enter the access code and click the following button.


The OCA brings together vendors and end users in an open cybersecurity ecosystem where products can freely exchange information, insights, analytics, and orchestrated response. The OCA supports commonly developed code and tooling and the use of mutually agreed upon technologies, data standards, and procedures.


Open Angel Arena 5.10.3 Update
General Changes
MMR changes: If you have less than 20 games then max MMR you can have is:
980 + (N x 5)
where N is number of finished games.
Hero Changes
Nature's Prophet:
Nature's Call: Fixed tooltip not showing the damage of the treants.
Wrath of Nature is now completely blocked by Spell Block if casted on the target with Spell Block.
Wrath of Nature now completely ignores units with spell immunity.
Damage was not piercing spell immunity anyway.
Wrath of Nature now completely ignores couriers.
Wrath of Nature: Fixed Wrath of Nature causing a server crash when cast on a target with Lotus Orb buff.
Wrath of Nature: Fixed Wrath of Nature cast sound emitting through fog of war.
You could locate Nature's Prophet in the fog because of this bug.
Wrath of Nature: Fixed Rubick (with Spell Steal) stealing Nature's Call together with Wrath of Nature.
Wrath of Nature (with Aghanim Scepter): Fixed Wrath of Nature bounces not applying a 4 second treant spawn debuff before damage is dealt.
This debuff is dispellable with any dispel and its not applied on units with spell immunity.
Wrath of Nature (with Aghanim Scepter): Damage rescaled from 140/170/340/510/680 to 140/
230
/
310
/510/680.
Zeus:
Nimbus doesn't prioritize heroes anymore.
Nimbus will hit the nearest unit. Its like this in normal dota.
Nimbus: Added mini-stun value to the tooltip.
This mini-stun value is not showing anywhere in normal dota, not even in the tooltip for Lightning Bolt.
.
Nimbus: Added Static Field damage to the Nimbus total damage. Static Field damage is applied first.
Static Field damage on Nimbus is amplified by Zeus' Spell Amplification. Its like this in normal dota.
Nimbus: Fixed Nimbus sounds emitting through fog of war.
You could locate Nimbus in the fog because of this bug.
Nimbus: Fixed Nimbus not having an AOE cast particle.
Nimbus: Fixed Nimbus cloud having collision.
Fixed Nimbus not working for Rubick when he steals it.
He was not stealing Lightning Bolt along with it.
Fixed Morphling, when morphed into Zeus, being able to have Nimbus even if Zeus doesn't have Aghanim Scepter.
Morphling can now have Nimbus only if both Zeus and Morphling have Aghanim Scepter.
Previous
Home
Next


mbsrtowcs
, mbsnrtowcs
—convert a character string to a wide-character string#include <wchar.h> size_t mbsrtowcs(wchar_t *__restrict dst, const char **__restrict src, size_t len, mbstate_t *__restrict ps); #include <wchar.h> size_t _mbsrtowcs_r(struct _reent *ptr, wchar_t *dst, const char **src, size_t len, mbstate_t *ps); #include <wchar.h> size_t mbsnrtowcs(wchar_t *__ restrict dst, const char **__restrict src, size_t nms, size_t len, mbstate_t *__restrict ps); #include <wchar.h> size_t _mbsnrtowcs_r(struct _reent *ptr, wchar_t *dst, const char **src, size_t nms, size_t len, mbstate_t *ps);
Description
The mbsrtowcs
function converts a sequence of multibyte characters
pointed to indirectly by src into a sequence of corresponding wide
characters and stores at most len of them in the wchar_t array pointed
to by dst, until it encounters a terminating null character ('\0').
If dst is NULL, no characters are stored.
If dst is not NULL, the pointer pointed to by src is updated to point to the character after the one that conversion stopped at. If conversion stops because a null character is encountered, *src is set to NULL.
The mbstate_t argument, ps, is used to keep track of the shift state. If
it is NULL, mbsrtowcs
uses an internal, static mbstate_t object, which
is initialized to the initial conversion state at program startup.
The mbsnrtowcs
function behaves identically to mbsrtowcs
, except that
conversion stops after reading at most nms bytes from the buffer pointed
to by src.
Returns
mbsrtowcs
and mbsnrtowcs
functions return the number of wide
characters stored in the array pointed to by dst if successful, otherwise
it returns (size_t)-1.
Portability
mbsrtowcs
is defined by the C99 standard.
mbsnrtowcs
is defined by the POSIX.1-2008 standard.


Protest over policing of NYC subways shuts station in Harlem
NEW YORK (AP) - A protest over the policing of New York City’s subways briefly shut down a busy Harlem subway station during rush hour, and news stations say multiple people have been arrested in the fluid demonstration.
News stations say hundreds of protesters converged Friday evening and marched on and near the major corridor of 125th Street.
Police spokesmen said they didn’t immediately have arrest information.
The New York Police Department tweeted around 7 p.m. that there were traffic and mass transit disruptions in the area.
A half-hour earlier, New York City Transit tweeted that three subway lines bypassed their 125 Street station for a time, then resumed stopping while police barred entry to the station for a while afterward.
The protesters are decrying what they consider heavy-handed law enforcement in the subways.
Sign up for Daily Newsletters
Copyright © 2019 The Washington Times, LLC.
Please read our comment policy before commenting.


Navbar
Home
(current)
Btns
Card
Modal
Modal 2
Checkbox
Search
Bootstrap 4 modal & tabs
Launch demo modal
×
Filter
preset 1
preset 2
Save As Preset
Event Date
Regions
All Regions
region 2
Promotions
All Promotions
Promotion 2
Ambassadors
All Ambassadors
ambassador 2
Workflow Actions
All Workflow Actions
action 2
Status


Preparation time
less than 30 mins
Cooking time
10 to 30 mins
Serves
Serves 4
This recipe takes a little time, but is worth the effort for some show-off cooking for your friends.
For the candied shallots, bring a pan of water to the boil. Simmer the shallots in the water for 5 minutes, then drain. Heat the butter in a frying pan, add the shallots and cook over a medium low heat until lightly browned. Add the sugar, heat gently and stir until the sugar starts to caramelise.
Mix the wine, port, cassis and stock in a jug. Add about a quarter of this to the pan of shallots, bring to the boil, then add the bay leaf, thyme and lemon zest. Keep adding the remaining liquid gradually, reducing each time, until the shallots are just covered with a lovely sticky glaze, then set aside until needed.
For the steaks, take the steaks out of the fridge an hour or so before cooking so that they are at room temperature.
Crumble the cheese into a bowl, then add the rosemary, lemon zest and garlic.
Using a sharp knife, cut a pocket horizontally in each steak, taking care not to cut all the way through the steak. Place one-quarter of the cheese stuffing into each pocket. Close the flap, and wrap a rasher of bacon around each steak, helping to seal the pocket. Secure with a cocktail stick.
Rub olive oil over the steaks, then sprinkle with salt and pepper to season.
Heat frying pan until hot and fry the steaks for 3-4 minutes on each side (for medium) or until cooked to your liking.
Allow the steaks to rest for 5 minutes. Meanwhile, gently reheat the shallots. Serve the steaks with the candied shallots.
A well-rounded merlot


pdg-control
- plots for changing costs
- Report out to Training Problem II group.
ggplot note
defining functions that return a ggplot object can be tricky. If you compute some objects in the plot function (stats etc), those stats are not stored by the object (due to lazy evaluation, usually a very nice time-saving feature), so the plot cannot be produced unless the function returns those things to the global environment (or from wherever the plot will be printed/evaluated). Can return them to the global env with “<<-” assignment, but seems poor form.
Evolution
power in phylogenies
- Hessian reply. manuscript reply.
- Select wrightscape examples.
wrightscape
- 1530089 series: bm vs a2 on parrotfish tree. looks like close & SH.y reject brownie, open almost does. kt almost does.
- 7a347b0 series: bm vs a1 on parrotfish tree: (missing lr line). More power, smaller diffs. Kt maybe? must rerun these!
- 4335204 bm vs a1 with the lines.
sig. open sig in reverse
cce5a5a/93a8630 series: labrid tree, intramandibular division, bm vs a1 (more power on larger tree, go for finer division between models?) only bodymass rejects. (cce5a5a missing lr line).
8382283 now running labrid bm vs a2.
- open & prot.y significant in reverse
- 6befae4 Check out open and kt on a2 vs bm when regime=two_shifts.
are significant. Close is significant reversed (funny pattern at a2 anyhow).
Make sure to run against standard ouch too!
Warning Signals
- Alan Manuscript
- Reading: re data sources (Dulvy et. al. 2003)
- (Le Quesne & Jennings, 2012)
- Example decisions under uncertainty of crash
Reading
- (Molloy, 2011)
- And on NC clause (Carroll, 2011), (Hagedorn et. al. 2011)
- Fiction: Non-commerical license means no one can make money from it. “I don’t want to give some entrepreneur a free lunch”
- Fact: NC means the journal (by holding the copyright) retains the right to sell your work to pharmaceuticals, teachers, researchers interested in text-mining, (rather than those groups having free use).
- Data reviews – F1000?
Graph gallery
[flickr-gallery mode=“search” tags=“phylogenetics, PDG_Control” min_upload_date=“2011-12-07 7:00:37” max_upload_date=“2011-12-08 12:23:37”]
References
Dulvy N, Sadovy Y and Reynolds J (2003). “Extinction Vulnerability in Marine Populations.” Fish And Fisheries, 4. ISSN 1467-2960, http://dx.doi.org/10.1046/j.1467-2979.2003.00105.x.
Le Quesne W and Jennings S (2012). “Predicting Species Vulnerability With Minimal Data to Support Rapid Risk Assessment of Fishing Impacts on Biodiversity.” Journal of Applied Ecology, 49. http://dx.doi.org/10.1111/j.1365-2664.2011.02087.x.
Molloy J (2011). “The Open Knowledge Foundation: Open Data Means Better Science.” Plos Biology, 9. http://dx.doi.org/10.1371/journal.pbio.1001195.
Carroll M (2011). “Why Full Open Access Matters.” Plos Biology, 9. http://dx.doi.org/10.1371/journal.pbio.1001210.
Hagedorn G, Mietchen D, Morris R, Agosti D, Penev L, Berendsohn W and Hobern D (2011). “Creative Commons Licenses And The Non-Commercial Condition: Implications For The re-Use of Biodiversity Information.” Zookeys, 150. ISSN 1313-2989, http://dx.doi.org/10.3897/zookeys.150.2189.


I never had a choice other than living in the future. Fighting, escaping and destroying "childhood", or "childishness", has always been my greatest utopia. The nostalgia, judging stares, unescapable isolation, loud classes, and saddening laughters, combined, just rot my soul.
The further away I got from this, the happier I got. Still, whenever I have reencounters, through a former school colleague, or similar humiliating situation, or memory, I immediately feel entrapped by its life-sucking claws.
And the issue is that there's childishnesss everywhere, in all ages.
Today, it's the ruling ideology.
Slaves and masters of their own ignorance and lethargy.
Kids, with their egocentric megalomanic dreams, primitive emotions, delusions of authenticity. Crowding together, little gangs, poisoning souls and rivers of indolence and feeble insurgency.
Self-deluded one might change the world with their desires and songs.  Apathetic sociopaths without any regard for anything outside their freudian instinctive urges.
 I can't fit , but I can just mind my business.
There is no time for stares, no humiliations, jealousy, mind games. They first need to survive.
Perhaps, I will always keep a menacing yet genuine child inside, the one I never got to live, but I'm glad to see the years passing by. With all my resentment, I have build unlimited and unstoppable force against them.
It may all be a fast rollercoaster, but it is one pointing up. That's what I live, that's what I see.
A sinoid with a positive slope.
I guess I was right. As time passes, metaphorically, my life turns into scotch, not dirty water .


For a limited time only - Sign up today and receive a free bong(Just pay for S&H). At MedCab we are dedicated to the health and wellness of our members. Our dedicated staff is here to make sure that you have what you need, by taking your symptoms and then returning a strain that is best suited for your needs. There is no hassle and no long lines to stand in. We are an easy to use app, so in order for you to get started all you need to do is simply sign up and log in, and let the best strain win.
Find Your Strain
Find strains based on the effects and taste in a database of thousands
Learn More
Explore what MedCab4 has to offer


- BinarySearchTree<E extends Comparable<E>> - Class in com.mycompany.hw6_131044084_mehmed_mustafa
-
A class to represent a binary search tree.
- BinarySearchTree() - Constructor for class com.mycompany.hw6_131044084_mehmed_mustafa.BinarySearchTree
-
- BinarySearchTree.Iterator<E> - Class in com.mycompany.hw6_131044084_mehmed_mustafa
-
- BinaryTree<E> - Class in com.mycompany.hw6_131044084_mehmed_mustafa
-
Class for a binary tree that stores type E objects.
- BinaryTree() - Constructor for class com.mycompany.hw6_131044084_mehmed_mustafa.BinaryTree
-
Construct an empty BinaryTree
- BinaryTree(BinaryTree.Node<E>) - Constructor for class com.mycompany.hw6_131044084_mehmed_mustafa.BinaryTree
-
Construct a BinaryTree with a specified root.
- BinaryTree(E, BinaryTree<E>, BinaryTree<E>) - Constructor for class com.mycompany.hw6_131044084_mehmed_mustafa.BinaryTree
-
Constructs a new binary tree with data in its root,leftTree
as its left subtree and rightTree as its right subtree.
- BinaryTree.Node<E> - Class in com.mycompany.hw6_131044084_mehmed_mustafa
-
Class to encapsulate a tree node.
- buildTree(HuffmanTree.HuffData[]) - Method in class com.mycompany.hw6_131044084_mehmed_mustafa.HuffmanTree
-
Builds the Huffman tree using the given alphabet and weights.


-
{{#each products}}
-
{{title}}
{{/each}}
Since we understand how hard it can be to find your favourite apps, we have carefully sorted each and every app into it's own category.
If you don't know which category an app may be in, you can use the Search tab below or you can choose a category and search for the app name.


A Special Text Editor
问题描述 :
1.The "Reverse" command has 2 parameters A and B.
The format is "R A B". After the command executed, the editor will reverse the substring which is in the string from position A to position B.
2.The "Shift" command also has 2 parameters A and B.
The format is "S A B". After the command executed, the editor will translate every character in the substring which is in the string from positon A to position B to the NEXT character in alphabetic table.In another word, it will translate ‘a’ to ‘b’,'b’ to ‘c’ … ‘y’ to ‘z’. Specially it will translate ‘z’ to ‘a’.
3.The "Query" command has only 1 parameter A.
The format is "Q A". When the text editor receives the command,it just reports the character which is in the postion A of the string now.
For example, let’s consider the string "abcdefzh" whose length is 8.
After we operate the command "R 2 7", the string will be "azfedcbh".
Then after we operate the command "S 2 3", it will be "aagedcbh".
Now your task is to simulate the process, and output the exact character when you read a "Query" command. Is that easy ? Just come and AC it !
输入:
In the first line there are two integers N(0<N<=80000) and C(0<C<=3000) which indicate the length of the string and the number of the commands.
In the second line there is a string whose length is N and which is only consisted of lowercase letters.
Then C lines follow. Each line describes a command in the form of ‘Q A’ or ‘R A B’ or ‘S A B’ (0<A<=B<=N).
输出:
In the first line there are two integers N(0<N<=80000) and C(0<C<=3000) which indicate the length of the string and the number of the commands.
In the second line there is a string whose length is N and which is only consisted of lowercase letters.
Then C lines follow. Each line describes a command in the form of ‘Q A’ or ‘R A B’ or ‘S A B’ (0<A<=B<=N).
题目太多了，很多解题报告是用程序自动发布的，所以就只有代码了
不是HDU 2411。。标题党么。。。
第一个数表示数列的个数，5表示之后有5个数
正在练习，很有帮助
厉害啊，我遇见数学问题就头疼！
不考虑最后将结果排序的话，快排的时间复杂度是O(N) ，而堆排的是O(N*logK)
程序员会算法，等于一个古惑仔带了zhi抢啊
不错的代码！
第36行，struct node **head_ref，怎么理解，那个函数感觉不是很懂啊！？？弱渣求助
原来欧几里德定理应用这么多
这代码的输出格式不对阿，else语句的low=p移动一下位置，增加可读性
真心不错，力顶作者


ESC Cancel the current task
F1 Displays Help
F2 Rename selected item
F3 Search for a file or folder
F4 Display the Address bar list in My Computer or Windows Explorer
F5 Refresh the active window
F6 Cycle through screen elements in a window or on the desktop
F10 Activate the menu bar in the active program
SHIFT+F10 Display the shortcut menu for the selected item
CTRL+ESC Display the Start menu
SHIFT+CTRL+ESC Launches Task Manager
SHIFT when you insert a CD Prevent the CD from automatically playing
WIN Display or hide the Start menu
WIN+BREAK Display the System Properties dialog box
WIN+D Minimizes all Windows and shows the Desktop
WIN+E Open Windows Explorer
WIN+F Search for a file or folder
WIN+F+CTRL Search for computers
WIN+L Locks the desktop
WIN+M Minimize or restore all windows
WIN+R Open the Run dialog box
WIN+TAB Switch between open items
Display the bottom of the active window. END
Display the top of the active window. HOME
Collapse the selected folder. NUM LOCK+MINUS SIGN on numeric keypad (-)
Collapse current selection if it's expanded, or select parent folder. LEFT ARROW
Display current selection if it's collapsed, or select first subfolder. RIGHT ARROW
Windows key + F = Search
Windows key + D = Hide/Display all windows
ALT, Space, X = Maximize window
Shift+Windows+M Undo minimize all open windows
CTRL+A Select all
CTRL+B Bold
CTRL+C Copy
CTRL+I Italics
CTRL+O Open an item
CTRL+U Underline
CTRL+V Paste
CTRL+X Cut
CTRL+Z Undo
CTRL+F4 Close the active document
CTRL while dragging Copy selected item
Move forward through tabs. CTRL+TAB
Move backward through tabs. CTRL+SHIFT+TAB
Move forward through options. TAB
Move backward through options. SHIFT+TAB
ALT+- (ALT+hyphen) Displays the Multiple Document Interface (MDI) child window's System menu ALT+ENTER View properties for the selected item
ALT+ESC Cycle through items in the order they were opened ALT+F4 Close the active item, or quit the active program
ALT+SPACEBAR Display the System menu for the active window
ALT+TAB Switch between open items
ALT+Underlined letter Display the corresponding menu
BACKSPACE View the folder one level up in My Computer or Windows Explorer
cleanmgr = Disk Cleanup
excel = Microsoft Excel (If Installed)
msaccess = Microsoft Access (If Installed)
powerpnt = Microsoft PowerPoint (If Installed)
winword = Microsoft Word (If Installed)
notepad = Notepad
wordpad = WordPad
calc = Calculator
mspaint = Microsoft Paint
wmplayer = Windows Media Player
control = Opens the Control Panel
control printers = Opens the Printers Dialog
Command Prompt -cmd
Disk Partition Manager- diskpart
On Screen Keyboard- osk
Registry Editor- regedit
Registry Editor- regedit32
Shuts Down Windows- shutdown
System Configuration Editor- sysedit
System Configuration Utility- msconfig
Task Manager- taskmgr
Windows Magnifier- magnify
Wordpad- write
© 2014 HaKTuts. All rights reserved.


Just sit abd watch the sea! 美丽总会相遇
Just the wonderful moment!
Let's see it It's an absolutly simple editor 2018.05.31