text:
Python sprints website
======================

This is the website of the Python sprints group.

It was started by the London Python Sprints meetup, but open to any other
Python User Group (PUG), interested in running sprints.

Website set up
--------------

The website is built using Jekyll, a Ruby (yes, Ruby ;) static website
generator supported by GitHub pages. To build the website locally you
need to:

- Install ruby and ruby-dev
    - `dnf install ruby ruby-devel` on Fedora, CentOS and RedHat
    - `apt-get install ruby-full ruby-dev` on Debian and Ubuntu
    - `brew install ruby` on MacOS
    - More information about installing Ruby is here
    <https://www.ruby-lang.org/en/documentation/installation/>.
- Install Jekyll with `gem install jekyll bundle`.
- Install dependencies with `bundle install` in the project directory.
- Run the server with `bundle exec jekyll serve`.
- Open the rendered website at http://localhost:4000/

How to add your chapter
-----------------------

Send a pull request adding a new file `_chapters/<your-chapter-name>.md`, where
`<your-chapter-name>` is the name of your chapter in ascii lowercase, and
separating words with underscore (e.g. `london_pyton_sprints`).

The content of the file has a header section with some fields (started and finished with
---), and the main description of the chapter afterwards.
We are using markdown files to store your data and they can contain either markdown tags for text formatting or pure html - it is up to you how to style your content.

The image that will represent your chapter should be in jpeg format. The size the content is optimized for is: 1920 x 600 px.
Please name it <your_chapter_name_1920x600px.jpg>.
This is the format:

    ---
    category: "the-city-where-your-chapter-is-located-in"
    title: "Name of your chapter"
    meetup_link: <url-of-your-other-website-if-any>
    address: "Description of your location, usually City, Country"
    country_code: <2-digit-country-code-used-for-the-flag>
    image: <relative path to the chapter image>
    lat: <float-number-with-latitude-for-the-marker-in-the-map>
    lng: <float-number-with-longitude-for-the-marker-in-the-map>
    sponsors:
        - <first-sponsor-id-to-be-listed-in-your-page>
        - <second-sponsor-id-to-be-listed-in-your-page>
        - <feel-free-to-add-as-many-as-you-want>
    ---

    Here you can add any information about your group. How it started, which are the goals,
    what people can expect from it.

    This is a good time to remind you, that no sort of discrimination (gender, religion,
    age, sexual orientation...) is tolerated in the Python sprints (or in the Python
    community in general). And as an organizer you must not allow any sort of harassment
    in the events. Feel free to add in your chapter description to policies you have to
    make sure the events are as diverse and welcoming as possible.

Example chapter setup
---------------------
    ---
    category: "london"
    title: "London Python Sprints"
    meetup_link: https://www.meetup.com/Python-Sprints/
    address: London, United Kingdom
    country_code: gb
    image: static/images/chapters/london_python_sprints_1920x600px.jpg
    lat: 51.512344
    lng: -0.090985
    sponsors:
      - harvey_nash
      - touch_surgery
      - bloomberg
    ---
    The content of your chapters description goes below ---.

How to add an event
-------------------

Before sending an event, you need to have your chapter set up. See the section *How to
add your chapter* for more information on how to do it.

You can also add a sponsor, to give credit to the companies/institutions supporting your
group with a venue, pizzas, beers... And if you are sprinting in a project not in the
system, you may also want to add it.

To create an event, you need to add a new file to the `_posts` directory with the file
name following the format `YYYY-MM-DD-slug-of-the-event.md`. Were `YYYY-MM-DD` is the
date of the event (this will be the date shown on site), and the slug of the event is the title in a format URL friendly
(only lowercase ascii letters and numbers, separating words with hyphens). For example
`2017-12-31-django-bugfixing.md` could be the name of a sprint "Django bugfixing"
happening on December 31st of 2017.

The content of the file has a header section with some fields (started and finished with
---), and the main description of the event afterwards. This is the format:

    ---
    category: "<same-as-category-of-your-chapter>"
    title: "Short summary of your event"
    level: "Target audience of the event (e.g. Beginners, All levels, Advanced,...)"
    time: "hh:mm"
    rsvp_link: <url-of-your-meetup-eventbrite-etc-page>
    project: <id-of-the-project-you-will-work-on>
    sponsor: <id-of-the-sponsor-for-the-event>
    ---

    This space is the main description of the event, where you can provide further details.

    Note that you don't need to add information about the project if it already exists in the `_projects` folder, as the description of the
    project, the logo, and the environment set up instructions should be rendered automatically
    after specifying the id of the project. If the project has not been added yet, you will need to add it before calling it here. If the event is not related to a specific project, you can leave the `<id-of-the-project-you-will-work-on>` blank.

    Also, by specifying the id of the sponsor, a box with its information will appear.

Example event setup
---------------------
    ---
    category: "london"
    title: "Pandas internals"
    level: "All levels"
    time: "18:30"
    rsvp_link: https://www.meetup.com/Python-Sprints/events/249350212/
    project: pandas
    sponsor: harvey_nash
    ---
    The content of your event's description goes below ---.

You may want to copy one of the last events in `_posts` to be used as reference.

How to add a sponsor
--------------------
If you need to add your local sponsor which is not already in the `_sponsors` folder you can do so easily.

To add a sponsor logo please copy it to the static/images/sponsors folder with a name matching the obj_id of your sponsor.
We use png files for our sponsors. The maximum size is: 258px x 82px so please scale them down to match one of those dimensions. The logo width is: 150px, if a logo having width smaller than that will be stretch to match the logo width.

Create a <name_of_your_sponsor>.md file using the format below:

    ---
    obj_id: <unique_identifier_of_your_sponsor>
    name: "name of your sponsor"
    logo: <relative path to your sponsor logo>
    link: <website link to your sponsor>
    address: "sponsor's full address"
    lat: <float-number-with-latitude-for-the-marker-in-the-map>
    lng: <float-number-with-longitude-for-the-marker-in-the-map>
    ---
    Here you can place a short description of your sponsor's business etc.

Example sponsor setup
---------------------
    ---
    obj_id: quantum_black
    name: "Quantum Black"
    logo: static/images/sponsors/quantum_black.png
    link: https://www.quantumblack.com/
    address: "Kinnaird House, 1 Pall Mall
London, SW1Y 5AU, UK"
    lat: 51.507954
    lng: -0.130718
    ---
    QuantumBlack is an advanced analytics firm operating at the intersection of strategy, technology & design to improve performance outcomes for organisations. With roots in Formula One, we now work across sector with some of the world's leading organisations in advanced industries, healthcare and finance.

How to add a project
--------------------
If you the project that you are going to work on is not already in the `_projects` folder you can do add it easily.

To add a project logo please copy it to the static/images/projects folder.
We use png files for projects.

Create a <name_of_your_project>.md file using the format below:

    ---
    obj_id: <unique_identifier_of_your_project>
    name: "name of your project"
    logo: <relative path to your project logo>
    website: <website link to your project>
    setup_html: |

    ---
    Here you can place a short description of your project.

Example project setup
---------------------
    ---
    obj_id: pandas
    name: "Pandas"
    logo: static/images/projects/pandas_logo_donation.png
    website: https://pandas.pydata.org/
    setup_html: |

            Please follow the instruction in this link:

                https://python-sprints.github.io/pandas/guide/index.html

    ---
    Pandas is an open source, BSD-licensed library providing high-performance, easy-to-use data structures and data analysis tools for the Python programming language.

How does Jekyll work?
---------------------

- Posts (files in `_posts/*.md`) are the event pages in markdown
- Projects (`_project/*.md`) are the open source projects we contribute to
- Sponsors (`_sponsors/*.md`) are the companies providing the venue and pizzas
- Layouts (files in `_layouts/*.html`) are equivalent to Django templates,
  and used to render the posts (events)
- CSS is managed with scss/sass and built by Jekyll
- GitHub pages automatically builds the site when the repository is updated


text:
# Proplagiopyxis Schönborn, 1964 GENUS

#### Status
ACCEPTED

#### According to
Interim Register of Marine and Nonmarine Genera

#### Published in
Limnologica, Berlin 2: 112.

#### Original name
null

### Remarks
null

repository: mdoering/backbone

branch_name: refs/heads/master

extension: md

license_type: permissive

repo_name: mdoering/backbone


text:
# Passive Cell Phone Detection

A hardware-based, non-invasive project to detect cell phone usage around a classroom and report where it was detected at.

Members:
Gavin Allcorn
Zack El-Mohandes

license: MIT

gha_license_id: MIT


text:
---
sidebar_position: 1
---

# Unit Tests

Testing contract functionality can be done through the `cargo test` framework. These tests will run with a mocked blockchain and will allow testing function calls directly without having to set up/deploy to a network and sign serialized transactions on this network.

A common framework for tests, along with setting up a basic testing environment looks like:

```rust
#[cfg(all(test, not(target_arch = "wasm32")))]
mod tests {
    use super::*;
    use near_sdk::test_utils::VMContextBuilder;
    use near_sdk::{testing_env, VMContext};

    fn get_context(is_view: bool) -> VMContext {
        VMContextBuilder::new()
            .signer_account_id("bob_near".parse().unwrap())
            .is_view(is_view)
            .build()
    }

    #[test]
    fn my_test() {
        let context = get_context(false);
        testing_env!(context);
        // ... Write test here
    }
}
```

Where `VMContextBuilder` allows for modifying the context of the mocked blockchain to simulate the environment that a transaction would be run. The documentation for what can be modified with this context can be found [here](https://docs.rs/near-sdk/latest/near_sdk/struct.VMContext.html).

The `testing_env!` macro will initialize the blockchain interface with the `VMContext` which is either initialized through `VMContextBuilder` or manually through itself.

:::info Note

This `testing_env!` and `VMContext` is only used for testing outside of `wasm` environments. When running the built contract on a network in a `wasm` environment, the context from the blockchain will be used through host functions on the runtime.

:::

To test read-only function calls, set `is_view` to `true` on the `VMContext`. This will test to verify that function calls which just read state do not try to modify state through unit tests. In the above example, `true` should be passed into the `get_context` call, which initializes the context as read-only.

You will want to use `testing_env!` each time you need to update this context, such as mocking the `predecessor_accound_id` to simulate the functions being called by or only allowing view operations as mentioned above. Each time this is done, a new mocked blockchain will be initialized while keeping the existing state.

repository: think-in-universe/docs

gha_language: TypeScript

repo_name: think-in-universe/docs


text:
# DroneControllerServer
An example server script to use in conjunction with "Drone Controller With Video" app on google playstore: https://play.google.com/store/apps/details?id=com.oxrockstudio.DroneRemoteControllerWithVideo

In an effort to improve accessibility as well as performance, you  now have the option to view MJPEG streams such as those used in the popular pi program Motion. Users controlling drones across vast distances should see an INCREDIBLE improvements to video response times if utilizing the new motion functionality.

Motion is really easy to setup especially with the help of a guide like this one: https://pimylifeup.com/raspberry-pi-webcam-server/

A server script will still need to run on your pi device to to handle drone inputs. if you're using motion for streaming video, you'll need to trim out the existing camera code. Using Motion is by no means mandatory. If your script worked in version 1.2, it will still work in version 1.25. Just make sure "Server Script" is selected from the drop down menu in video options.

The provided sample code should work for either python 2 or 3, although it was tested mainly on 2.7. If you're using this code on a raspberry pi, then I suggest trying to get it working on python 2 if possible. This script requires opencv which can be a larger hassle to install properly for python 3 on raspberry pi devices.

Installing opencv for python2 on pi should be simply accomplished by the following(If not using motion to handle video streaming):

sudo apt-get install python-numpy

sudo apt-get install python-scipy

sudo apt-get install python-opencv

camServer_v1.2.py is for communicating with Drone Controller With Video versions 1.2 and above.

camServer_OLD.py is for communicating with Drone Controller With Video versions 1.15 and below.

It is highly reccomended that you disable wifi powersave mode if you're streaming wirelessly. You can do so with the following command: sudo iw wlan0 set power_save off

It can also be beneficial to update your pi with the following commands:

sudo apt-get update

sudo apt-get dist-upgrade

sudo rpi-update

repository: oxrock/DroneControllerServer

gha_language: Python

repo_name: oxrock/DroneControllerServer


text:
---
title: "Hero Wanted campaign for fixing final bugs launches!"
excerpt: "We are all working hard on fixing the remaining issues for delivering a stable Godot 3.0 as soon as possible, but we
definitely need a hand to speed up the work!"
categories: ["news"]
author: Juan Linietsky
image: /storage/app/uploads/public/5a2/806/8a7/5a28068a7039e549952344.png
date: 2017-12-06 00:00:00
---

We are all working hard on fixing the remaining issues for delivering a stable Godot 3.0 as soon as possible, but we
definitely need a hand to speed up the work!

Because of this, we are re-launching the Hero Wanted campaign, this time it's the ultimate battle!

### Hero Wanted (v2)

While most issues require more experience with the codebase, we have marked a [good amount of issues](https://github.com/godotengine/godot/issues?q=is%3Aissue+is%3Aopen+label%3A%22hero+wanted%21%22) with the "Hero Wanted!" tag. They include a description on how the problem can be approached, so it's great for new contributors unfamiliar with the code.

Feel free to join irc (#godotengine-devel) if you need assistance from other devs. We are counting on you!

repository: godotengine/godot-website

gha_language: HTML

repo_name: godotengine/godot-website


text:
# headerFileAnalysis
C/C++ include files analysis

## Usage

Linux 下使用
``` bash

# Compiler
bash build.sh
# 或者使用 make
make

# Run (use Lua as a Example)
./headerFileAnalysis path/to/your/project/

```

## How to generate .dot file to a picture

1. install graphviz. if you use Ubuntu OS, run
``` bash

sudo apt-get install graphviz

```

if you use Windows. download it from [graphviz website](https://graphviz.org/download/)
don't forget add graphviz to your system path.

2. install VScode plugin  Graphviz Preview(author: EFanZh)

3. in VSCode, open a dot file, then you can find a button on upper left of the window.
click it, you can see a picture like

### use command line to generate output file

```bash
# pdf format
$ dot -Tpdf -o output.pdf input.dot
# svg format
$ dot -Tsvg -o output.svg input.dot
```
mor output format see [Graphviz Output Formats Document](https://graphviz.org/docs/outputs/)

![lua_include_graph.svg](./lua_include_graph.svg)

![ocaml_include_graph.svg](./ocaml_include_graph.svg)

![cpython_include_graph.svg](./cpython_include_graph.svg)

repository: LiuYinCarl/headerFileAnalysis

branch_name: refs/heads/main

repo_name: LiuYinCarl/headerFileAnalysis


text:
### Install

```shell
npm install --save detect-node
```

### Usage:

```js
var isNode = require('detect-node');

if (isNode) {
  console.log("Running under Node.JS");
} else {
  alert("Hello from browser (or whatever not-a-node env)");
}
```

The check is performed as:
```js
module.exports = false;

// Only Node.JS has a process variable that is of [[Class]] process
try {
 module.exports = Object.prototype.toString.call(global.process) === '[object process]'
} catch(e) {}

```

Thanks to Ingvar Stepanyan for the initial idea. This check is both **the most reliable I could find** and it does not use `process` env directly, which would cause browserify to include it into the build.

repository: iliakan/detect-node

gha_language: JavaScript

repo_name: iliakan/detect-node


text:
A simple server-side rendered React App with 360 view.

## Available Scripts

In the project directory, you can run:

### `yarn install`

To install the dependencies

### `yarn start`

Runs the app in the development mode.

Open [http://localhost:8080](http://localhost:8080) to view it in the browser.

The page will reload if you make edits.

You will also see any lint errors in the console.

### `yarn build`

To make client side build in `dist/client.js` folder.

### `yarn deploy`

To make server side build in `dist/server.js` folder.

It correctly bundles React in production mode and optimizes the build for the best performance.

Open [http://localhost:3000](http://localhost:3000) to view it in the browser.

branch_name: refs/heads/heroku


text:
---
layout: article
title: 'ARM Lab 2: Functions & sources of template information'
date: 2018-01-08
categories: null
tags: [authoring, arm, workshop, hackathon, lab, template, functions]
comments: true
author: Richard_Cheney
previous:
  url: ../arm-lab1-firstTemplate
  title: Creating your first template
next:
  url: ../arm-lab3-referencesAndSecrets
  title: Referencing resource properties and using secrets
---

{% include toc.html %}

## Overview

The snippets we used in lab 1 are very useful and easy to use.  They meet most basic needs, but they have a couple of significant failings:
* They are not actively maintained and therefore do not include all of the new functionality
* They do not cover all of the services available on Azure

In this lab we will create templates from some of the other major sources of resource type information to speed up the templating process and enable us to deploy infrastructure as code for some of the higher value services available on the Azure platform, or to make use of newer functionality.

1. First we will use the export functionality from the portal immediately prior to submission
1. We will then use the semi-hidden ARM template editor in the portal
1. Finally we will leverage some of the IP on the Azure quickstart templates on GitHub

But before we start moving through those areas, let's take a few moments to look at the wealth of functions that are available to the ARM templates.  We'll start to see more of them as we work through the various sections of the lab so it is worth spending some time to understand that range of capability.

## ARM Template Functions

The documentation for the ARM template functions is one of those areas that you will visit often, and the short URL **https://aka.ms/armfunc** will take you straight there.

We'll now step through some of the functions available to ARM templates, and how they can be used.  This will not cover all of them, as the [documentation](https://aka.ms/armfunctions) for the templates is pretty good, so if you need to understand something trivial like how to trim a string with whitespace then dive in to that area and dig out the information.

The functions are split into seven groups:
1. **[Array and object](https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-template-functions-array)**: used to manipulate or test JSON arrays and objects
1. **[Comparison](https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-template-functions-comparison)**: which are a group of test operators used by the **condition** function
1. **[Deployment](https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-template-functions-deployment)**: which covers those related to the deployment job, e.g. the parameters and variables functions
1. **[Logical](https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-template-functions-logical)**: which are a group used in logical expressions, such as _if_,  _and_ and _or_, or converting strings to booleans
1. **[Numerical](https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-template-functions-numeric)**: the group providing integer and floating point arithmetic operators
1. **[Resource](https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-template-functions-resource)**: a very useful set for working with Azure Resource Manager constructs, such as info and IDs for the subscription, resource group, resources and providers, plus keys of resources, and references to a resources current state
1. **[Strings](https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-template-functions-string)**: and the final set provides a large set of functions to manipulate and test strings

Browse through the section to understand the breadth of functions available.

Another way of thinking about functions is to split them into those used to:
* get
* manipulate
* test

You will see many of these functions used by some of the more complex templates that we will come across as we continue to work through the labs.

------------------

## Exporting templates from the portal

We'll now look at different places to source templates and we'll start with exporting templates directly out of the Azure portal itself.  There are a couple of ways of doing this:
1. viewing the _automation options_ prior to resource deployment
1. creating a full export of a whole resource group

Both have their benefits and limitations and the labs will hopefully illustrate this.  This is also a good lab to talk about API versions and to start utilising the reference documentation.

We'll see that the snippets we've been using can be a little outdated and missing certain new capabilities.  We will use the export to get a more up to date version, and in combination with the reference material we will then update the template to create the parameterisation options that we want for our standardised deployment.

We'll then show how you can use the full resource group export to compare before and after template definitions to capture manual changes to a resource and then represent that in your template.  The template reference documentation does not often provide examples of the expected property values, so this can be a useful tool.

### Comparing snippets against the reference documentation

Let's look at the snippets for web apps.  When you create a web app, it also needs an app service plan.

* Create a new azuredeploy.json template in a lab2a folder.
* Add in two new snippets to your array of resources:
  * arm-plan
  * arm-webapp

You will have to have a comma between the resources to avoid the telltale red lines that signify a syntax error.

Look at the apiVersion property for the two resource and you will notice that the API versions for both are a little old:

**Resource.Provider/type** | **Snippet apiVersion**
Microsoft.Web/serverfarms | 2014-06-01
Microsoft.Web/site | 2015-08-01

If you search on "arm template reference" then the top link will have the information on how to access reference materials on the resource types.  You will find yourself returning to this page quite often, so it is useful that someone has set up another short URL to take you straight to the page: **https://aka.ms/armref**.  That is another short URL that is worth memorising if you end up spending a lot of time working on templates.

The full pathing to take you direct to individual resource type pages is  https://docs.microsoft.com/en-gb/azure/templates/_resource.provider_/_type_, so for the two resources in our template it would be:

**Resource.Provider/type** | **Snippet apiVersion**
[Microsoft.Web/serverfarms](https://docs.microsoft.com/en-gb/azure/templates/Microsoft.Web/serverfarms) | 2016-09-01
[Microsoft.Web/sites](https://docs.microsoft.com/en-gb/azure/templates/Microsoft.Web/sites) | 2016-08-01

Note that not all enhancements to an Azure service require a change to the JSON schema for the service.  Many enhancements can be accommodated as additional values for existing properties within the current schema.

Note that there does not appear to be a way of seeing the full reference documentation for older API versions.  Also there can be a slight lag between new functionality being available and the reference documentation being updated.  For that you can search for the resource type in the [GitHub repo](https://github.com/Azure/azure-resource-manager-schemas/tree/master/schemas).  This will find the updated schema sections for the resource type that are pulled together for the full resource provider schema.  Understanding this in depth is outside of the scope of the lab.

### Exporting from the portal

OK, let's export an example template and parameters file.

**Follow the steps below, but make sure you stop just prior to submission via the final 'Create' button.**

* Open the Azure [portal(https://portal.azure.com)]
* Click **+ Add** on the left
* Search for "Web App"
* Select and click on Create
  * App Name: **\<yourname>arm** (has to be unique)
  * Resource Group: Create New, called **lab2a**
  * App Service Plan / Location: Click on the **>** arrow
    * Create new
    * App Service Plan: **Free**
    * Location: **West Europe**
    * Pricing tier: **F1 Free**

**_DO NOT CLICK ON THE CREATE BUTTON!_** Click on the _Automation Options_ link instead.

This will open up the template that the portal has created on the fly.  If you tab through the Template, Parameters, CLI, PowerShell, .NET and Ruby tabs then you will see the two JSON templates, plus deployment code for the various CLIs and key SDKs.

Let's copy out the template and parameter file into lab2a folder of our project as azuredeploy.json and azuredeploy.parameters.json respectively.

### Factoring parameters and variables

Examine the resources.  You'll notice that both are newer than the snippets, but whilst the App Service plan (serverfarm) is up to date, the Web App (sites) is a little out.  You will also notice that pretty much everything is parameterised.

Here are the example initial files:

```json
{
    "parameters": {
        "name": {
            "type": "string"
        },
        "hostingPlanName": {
            "type": "string"
        },
        "hostingEnvironment": {
            "type": "string"
        },
        "location": {
            "type": "string"
        },
        "sku": {
            "type": "string"
        },
        "skuCode": {
            "type": "string"
        },
        "workerSize": {
            "type": "string"
        },
        "serverFarmResourceGroup": {
            "type": "string"
        },
        "subscriptionId": {
            "type": "string"
        }
    },
    "resources": [
        {
            "apiVersion": "2016-03-01",
            "name": "[parameters('name')]",
            "type": "Microsoft.Web/sites",
            "properties": {
                "name": "[parameters('name')]",
                "serverFarmId": "[concat('/subscriptions/', parameters('subscriptionId'),'/resourcegroups/', parameters('serverFarmResourceGroup'), '/providers/Microsoft.Web/serverfarms/', parameters('hostingPlanName'))]",
                "hostingEnvironment": "[parameters('hostingEnvironment')]"
            },
            "location": "[parameters('location')]",
            "tags": {
                "[concat('hidden-related:', '/subscriptions/', parameters('subscriptionId'),'/resourcegroups/', parameters('serverFarmResourceGroup'), '/providers/Microsoft.Web/serverfarms/', parameters('hostingPlanName'))]": "empty"
            },
            "dependsOn": [
                "[concat('Microsoft.Web/serverfarms/', parameters('hostingPlanName'))]"
            ]
        },
        {
            "apiVersion": "2016-09-01",
            "name": "[parameters('hostingPlanName')]",
            "type": "Microsoft.Web/serverfarms",
            "location": "[parameters('location')]",
            "properties": {
                "name": "[parameters('hostingPlanName')]",
                "workerSizeId": "[parameters('workerSize')]",
                "reserved": false,
                "numberOfWorkers": "1",
                "hostingEnvironment": "[parameters('hostingEnvironment')]"
            },
            "sku": {
                "Tier": "[parameters('sku')]",
                "Name": "[parameters('skuCode')]"
            }
        }
    ],
    "$schema": "http://schema.management.azure.com/schemas/2014-04-01-preview/deploymentTemplate.json#",
    "contentVersion": "<IP_ADDRESS>"
}
```

Configure VS Code to have both the azuredeploy.json and the azuredeploy.parameters.json side by side.

![vscode](/workshops/arm/images/lab2-1-vscode.png)

We have a few too many parameters for our service so let's refactor it down to a completely minimal set of parameters, i.e. just the Web App name.  The quickest way to hardcode or derive certain options is to move them down to the variables section.

Quick guide:

1. Add in a variables section
1. Create variable names to match the names of parameters to be "moved"
  1. Hardcode the values where sensible
  1. Derive the values where possible
1. Remove parameters that are no longer required
1. Change the appropriate parameter calls in the resources section to variable calls
1. Add in default values and allowed values for remaining parameters
1. Strip down the parameters file to only the required parameter values
1. Test

Here is a video that shows example files being edited.  (Note the use of CTRL-F2 in VS Code to Change All Occurrences.)

<video video width="800" height="600" controls autoplay muted>
  <source type="video/mp4" src="/workshops/arm/images/lab2-2-refactoringExport.mp4"></source>

Your browser does not support the video element.

</video>

Note that from this point onwards only the bash commands will be shown for brevity.  It is not difficult to create the corresponding PowerShell commands.  If you are running CLI 2.0 within PowerShell then explicitly state the string variables rather than derive them from other variables or command output.

```bash
rg=lab2
template=$(pwd)/lab2a/azuredeploy.json
parms=$(pwd)/lab2a/azuredeploy.parameters.json
job=job.$(date --utc +"%Y%m%d.%H%M")
az group deployment create --name $job --parameters "@$parms" --template-file $template --resource-group $rg
```

### Final lab2a files

###### Lab 2a Files:

          azuredeploy.json

          azuredeploy.parameters.json

Note the 'dependsOn' property in the main azuredeploy.json.  This is an explicit dependency.

You will also see implicit dependencies, where resource properties in one resource are derived from the properties of another resources.  Again, the Azure Resource Manager layer will intelligently understand the implicit relationship and will order the resource creation accordingly.

### Exporting a whole resource group definition

It is possible to export a whole resource group definition as ARM JSON.  This is very verbose and it will hardcode many of the property values.  However, it is useful to compare the files before and after a manual change to see how that can be driven using ARM.

1. Open up the blade for the resource group once it has successfully deployed
1. Click on Automation Script in the Settings section
1. Copy out the JSON into a new file within VS Code
1. Open up the Web App blade
1. Select CORS in the API section
1. Enter in a valid origin site and port, e.g. `http://azurecitadel.github.io:1976`
1. Click on Save
1. Go back up to the resource group and click on Automation Script again
1. Copy out the "after" version of the JSON and paste it into another new file in VS Code
1. Use the 'File: Compare Active File With...' to see the difference

![Compare](/workshops/arm/images/lab2-3-compareRgExports.png)

If you take a look at the [web app reference page](https://docs.microsoft.com/en-gb/azure/templates/microsoft.web/sites) then you'll find the CORS property and you will also see that it is comparatively well described.  This is not always the case for some of the other resource properties, so this before and after comparison is a handy way of checking the format of the string, array or object that is expected.

-----------

## Template editor in the Azure portal

The second way of getting resources is to use the Azure Resource Manager template editor that is built into the portal itself.  The Templates area in the portal allows you to save templates you use repeatedly, and the portal is one of the many possible deployment types.

The Templates editor is a little hidden away, so you have to search on "templates" in the search bar at the top of the [portal](https://ms.portal.azure.com/#create/Microsoft.Template).

![Template Editor](/workshops/arm/images/searchTemplatesInPortal.png)

1. Click on the "Build you own template in the editor" link
1. Add in a Storage Account, with "sa" as the prefix
1. Add in a Virtual Network, called "vnet"
1. Add in an Ubuntu server, called "myUbuntuServer"
  1. Select the "sa" Storage Account
  1. Select the "vnet" Virtual Network
1. Save, or copy and paste out the contents into your own azuredeploy.json file in a lab2b folder.

Here is the resulting template:

```json
{
    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
    "contentVersion": "<IP_ADDRESS>",
    "parameters": {
        "saType": {
            "type": "string",
            "defaultValue": "Standard_LRS",
            "allowedValues": [
                "Standard_LRS",
                "Standard_ZRS",
                "Standard_GRS",
                "Standard_RAGRS",
                "Premium_LRS"
            ]
        },
        "myUbuntuServerName": {
            "type": "string",
            "minLength": 1
        },
        "myUbuntuServerAdminUserName": {
            "type": "string",
            "minLength": 1
        },
        "myUbuntuServerAdminPassword": {
            "type": "securestring"
        },
        "myUbuntuServerUbuntuOSVersion": {
            "type": "string",
            "defaultValue": "14.04.2-LTS",
            "allowedValues": [
                "12.04.5-LTS",
                "14.04.2-LTS",
                "15.04"
            ]
        }
    },
    "resources": [
        {
            "name": "[variables('saName')]",
            "type": "Microsoft.Storage/storageAccounts",
            "location": "[resourceGroup().location]",
            "apiVersion": "2015-06-15",
            "dependsOn": [],
            "tags": {
                "displayName": "sa"
            },
            "properties": {
                "accountType": "[parameters('saType')]"
            }
        },
        {
            "name": "vNet",
            "type": "Microsoft.Network/virtualNetworks",
            "location": "[resourceGroup().location]",
            "apiVersion": "2015-06-15",
            "dependsOn": [],
            "tags": {
                "displayName": "vNet"
            },
            "properties": {
                "addressSpace": {
                    "addressPrefixes": [
                        "[variables('vNetPrefix')]"
                    ]
                },
                "subnets": [
                    {
                        "name": "[variables('vNetSubnet1Name')]",
                        "properties": {
                            "addressPrefix": "[variables('vNetSubnet1Prefix')]"
                        }
                    },
                    {
                        "name": "[variables('vNetSubnet2Name')]",
                        "properties": {
                            "addressPrefix": "[variables('vNetSubnet2Prefix')]"
                        }
                    }
                ]
            }
        },
        {
            "name": "[variables('myUbuntuServerNicName')]",
            "type": "Microsoft.Network/networkInterfaces",
            "location": "[resourceGroup().location]",
            "apiVersion": "2015-06-15",
            "dependsOn": [
                "[concat('Microsoft.Network/virtualNetworks/', 'vNet')]"
            ],
            "tags": {
                "displayName": "myUbuntuServerNic"
            },
            "properties": {
                "ipConfigurations": [
                    {
                        "name": "ipconfig1",
                        "properties": {
                            "privateIPAllocationMethod": "Dynamic",
                            "subnet": {
                                "id": "[variables('myUbuntuServerSubnetRef')]"
                            }
                        }
                    }
                ]
            }
        },
        {
            "name": "[parameters('myUbuntuServerName')]",
            "type": "Microsoft.Compute/virtualMachines",
            "location": "[resourceGroup().location]",
            "apiVersion": "2015-06-15",
            "dependsOn": [
                "[concat('Microsoft.Storage/storageAccounts/', variables('saName'))]",
                "[concat('Microsoft.Network/networkInterfaces/', variables('myUbuntuServerNicName'))]"
            ],
            "tags": {
                "displayName": "myUbuntuServer"
            },
            "properties": {
                "hardwareProfile": {
                    "vmSize": "[variables('myUbuntuServerVmSize')]"
                },
                "osProfile": {
                    "computerName": "[parameters('myUbuntuServerName')]",
                    "adminUsername": "[parameters('myUbuntuServerAdminUsername')]",
                    "adminPassword": "[parameters('myUbuntuServerAdminPassword')]"
                },
                "storageProfile": {
                    "imageReference": {
                        "publisher": "[variables('myUbuntuServerImagePublisher')]",
                        "offer": "[variables('myUbuntuServerImageOffer')]",
                        "sku": "[parameters('myUbuntuServerUbuntuOSVersion')]",
                        "version": "latest"
                    },
                    "osDisk": {
                        "name": "myUbuntuServerOSDisk",
                        "vhd": {
                            "uri": "[concat('http://', variables('saName'), '.blob.core.windows.net/', variables('myUbuntuServerStorageAccountContainerName'), '/', variables('myUbuntuServerOSDiskName'), '.vhd')]"
                        },
                        "caching": "ReadWrite",
                        "createOption": "FromImage"
                    }
                },
                "networkProfile": {
                    "networkInterfaces": [
                        {
                            "id": "[resourceId('Microsoft.Network/networkInterfaces', variables('myUbuntuServerNicName'))]"
                        }
                    ]
                }
            }
        }
    ],
    "variables": {
        "saName": "[concat('sa', uniqueString(resourceGroup().id))]",
        "vNetPrefix": "<IP_ADDRESS>/16",
        "vNetSubnet1Name": "Subnet-1",
        "vNetSubnet1Prefix": "<IP_ADDRESS>/24",
        "vNetSubnet2Name": "Subnet-2",
        "vNetSubnet2Prefix": "<IP_ADDRESS>/24",
        "myUbuntuServerImagePublisher": "Canonical",
        "myUbuntuServerImageOffer": "UbuntuServer",
        "myUbuntuServerOSDiskName": "myUbuntuServerOSDisk",
        "myUbuntuServerVmSize": "Standard_D1",
        "myUbuntuServerVnetID": "[resourceId('Microsoft.Network/virtualNetworks', 'vNet')]",
        "myUbuntuServerSubnetRef": "[concat(variables('myUbuntuServerVnetID'), '/subnets/', variables('vNetSubnet1Name'))]",
        "myUbuntuServerStorageAccountContainerName": "vhds",
        "myUbuntuServerNicName": "[concat(parameters('myUbuntuServerName'), 'NetworkInterface')]"
    }
}
```

This is a very quick way of creating some of the most commonly used template resources, and it is nice in that it creates a mix of resources, variables and parameters.

On the negative side, be aware that the OS disks in this template are the older storage account version, rather than Managed Disks, and that the API versions are all from the middle of 2015.

As soon as you click on the Save button then you will be taken to the dialog blade where, as a user, you can enter the parameters expected by the template.  This then gives you the opportunity to edit and copy out both the template and the parameters file.

###### Lab 2b Files:

          azuredeploy.json

          azuredeploy.parameters.json

And once you have them in VS Code then you can refactor the parameters and variables to meet your requirements, or update a resources sections to a newer API version.

Note the cleartext password in the parameter file.  This does not follow our best practices for secure strings when you are deploying using parameter files.  More in that in lab 3.

-----------------------------------

## Azure Quickstart templates

In the previous section we were working in the portal, and you may have noticed the "Load a GitHub quickstart template" option.  There is a GitHub repo that has a wide selection of ARM templates that have been contributed by both Microsoft employees and by the wider community.  You can find it by searching for "Azure quickstart templates", which will find both the main [Azure Quickstart GitHub repo](https://github.com/Azure/azure-quickstart-templates) and the [Azure Quickstart Templates portal](https://azure.microsoft.com/en-gb/resources/templates/) site that helps to navigate some of the content.

There is yet another short URL to take you straight through to the GitHub repo, which is https://aka.ms/armtemplates.

Go via either route and search for "deploy a simple linux VM".  You'll find a number of templates, but we'll take a look at the "101-vm-simple-linux" template that has been contributed by Brian Moore, one of the Microsoft employees based in Fargo.  If you have gone through the Microsoft Azure route, then select the  Browse on GitHub button.  You should now be [here](https://github.com/Azure/azure-quickstart-templates/tree/master/101-vm-simple-linux).

You will find the azuredeploy.json and azuredeploy.parameters.json as expected.  There are also a couple of other files that are there for the repo to work as expected:

1. **metadata.json** contains the information that dictates how the entry is shown in the Microsoft Azure Quickstart Templates site.  The parameters information is pulled directly from the azuredeploy.json, pulling out the parameter name and metadata description.
1. **readme.md** is a readme file in markdown format.  Click on the raw format to see how the markdown is written and rendered into the static HTML that you see when browsing the GitHub repo itself.

Copy out the azuredeploy.json and azuredeploy.parameters.json out into new files in a lab2c folder. This is easier when looking at the raw versions.

###### Lab 2c Files:

          azuredeploy.json

          azuredeploy.parameters.json

The 101-vm-simple-linux template is one of the simpler templates, but it gives us an opportunity to see how a virtual machine is constructed, and some of the common practices when developing templates.

#### Parameters

The parameters are well defined in the template with sensible defaults and allowed values for the ubuntuOSVersion.  As mentioned above, the metadata.description is set for each as this is used in the Microsoft Azure overview page.

Looking at the corresponding azuredeploy.parameters.json file, it is usual to pass the first three parameters, admin user and password, and the DNS label for the public IP.  Note again that the password string is defined as a securestring, so once deployed you will not be able to see the value, but the password will be in clear text in the parameters file.

We will address this soon enough, looking at two different ways of preventing unwanted access to secrets:
* using secrets held in Key Vault
* controlling access to JSON files hosted centrally

These will both be covered in future labs.

  There is always the option to refactor some of these up into the parameters section, such as vmName, vmSize, subnet names etc.

Using good variable names makes the main resource section much easier to read and understand, especially if it means that you avoid length concat functions for the resource IDs.

#### Resources

One thing that is not necessary, but is very good practice, is to put the resources in rough order of instantiation.  You can see that in this template.

The storage account, public IP (PIP) and vNet are created first as they have no dependencies.  They will be deployed in parallel by ARM.  Note also that a single subnet is created as a child resource in the vNet.

The NIC is then created.  Pay attention to the dependsOn array, which contains the resourceId function for both the vNet and the PIP.  These cannot be predefined as a variable as those resources are not available at the time of interpretation.  But ARM will see those and make the appropriate dependencies, taking the ID from those resources once they have been created.

And finally we have the virtual machine itself which has dependencies on both the NIC and the storage account.  You will see all of these resources when you look at the resource group after a successful deployment.

It is worth taking a moment to look at the [virtual machines reference](https://docs.microsoft.com/en-gb/azure/templates/microsoft.compute/virtualmachines) area as a virtual machine is actually one of the most complicated resources within Azure.  This template is only using a small subset of the number of possible properties in this resource type.  We will be using one of those in the next lab, in order to use a password that has been stored as a secret in Key Vault and pass that through as securetext.

Also take a look at the sub-resource type that you can have within virtual machines, the [virtual machines extensions reference](https://docs.microsoft.com/en-gb/azure/templates/microsoft.compute/virtualmachines/extensions) area. This is how you can extend the virtual machines to automatically add in virtual machine agents such as antimalware, Operations Management Suite (OMS), diagnostics, Desired State Configuration (DSC) and third party extensions such as the plugin for Chef.

When defining your building block standards for key resource types such as virtual machines, use the documentation available in the Azure Docs area.  For example, there is some fantastic information on the site for both [Windows](https://docs.microsoft.com/en-us/azure/virtual-machines/windows/) and [Linux](https://docs.microsoft.com/en-us/azure/virtual-machines/linux/) virtual machines to enable you to customise your standard build and build up your own IP.

#### Outputs

The last section is probably the most optional out of all of the ARM template sections, but you will start to make more and more use of it if you start to nest templates, or wrap them up in other scripting.

If you have been deploying the templates using the bash CLI with the standard JSON output, then you will see that you have some standard JSON information outputted by each deployment.  You can customise that output using the output section.  In this template it is adding in both the server's hostname, and the ssh connection string to connect to a terminal session.

Check the truncated JSON output below from a test deployment and find the outputs object:

```json
{
  "id": "/subscriptions/2ca40be1-7680-4f2b-92f7-06b2123a68cc/resourceGroups/lab2/providers/Microsoft.Resources/deployments/job.20171208.0830",
  "name": "job.20171208.0830",
  "properties": {
    "correlationId": "9306d86d-3910-41d1-a098-63aab6a2f243",
    "debugSetting": null,
    "dependencies": [
      {
        "dependsOn": [
          {
            "id": "/subscriptions/2ca40be1-7e80-4f2b-92f7-06b2123a68cc/resourceGroups/lab2/providers/Microsoft.Network/publicIPAddresses/myPublicIP",
            "resourceGroup": "lab2",
            "resourceName": "myPublicIP",
            "resourceType": "Microsoft.Network/publicIPAddresses"
          },
          {
            "id": "/subscriptions/2ca40be1-7e80-4f2b-92f7-06b2123a68cc/resourceGroups/lab2/providers/Microsoft.Network/virtualNetworks/MyVNET",
            "resourceGroup": "lab2",
            "resourceName": "MyVNET",
            "resourceType": "Microsoft.Network/virtualNetworks"
          }
        ],
        "id": "/subscriptions/2ca40be1-7e80-4f2b-92f7-06b2123a68cc/resourceGroups/lab2/providers/Microsoft.Network/networkInterfaces/myVMNic",
        "resourceGroup": "lab2",
        "resourceName": "myVMNic",
        "resourceType": "Microsoft.Network/networkInterfaces"
      },
      {
        "dependsOn": [
          {
            "id": "/subscriptions/2ca40be1-7e80-4f2b-92f7-06b2123a68cc/resourceGroups/lab2/providers/Microsoft.Storage/storageAccounts/bgsjx5attarpasalinuxvm",
            "resourceGroup": "lab2",
            "resourceName": "bgsjx5attarpasalinuxvm",
            "resourceType": "Microsoft.Storage/storageAccounts"
          },
          {
            "id": "/subscriptions/2ca40be1-7e80-4f2b-92f7-06b2123a68cc/resourceGroups/lab2/providers/Microsoft.Network/networkInterfaces/myVMNic",
            "resourceGroup": "lab2",
            "resourceName": "myVMNic",
            "resourceType": "Microsoft.Network/networkInterfaces"
          },
          {
            "id": "/subscriptions/2ca40be1-7e80-4f2b-92f7-06b2123a68cc/resourceGroups/lab2/providers/Microsoft.Storage/storageAccounts/bgsjx5attarpasalinuxvm",
            "resourceGroup": "lab2",
            "resourceName": "bgsjx5attarpasalinuxvm",
            "resourceType": "Microsoft.Storage/storageAccounts"
          }
        ],
        "id": "/subscriptions/2ca40be1-7e80-4f2b-92f7-06b2123a68cc/resourceGroups/lab2/providers/Microsoft.Compute/virtualMachines/MyUbuntuVM",
        "resourceGroup": "lab2",
        "resourceName": "MyUbuntuVM",
        "resourceType": "Microsoft.Compute/virtualMachines"
      }
    ],
    "mode": "Incremental",
    "outputs": {
      "hostname": {
        "type": "String",
        "value": "richeneyvm.westeurope.cloudapp.azure.com"
      },
      "sshCommand": {
        "type": "String",
        "value": "ssh<EMAIL_ADDRESS>      }
    },
    "parameters": {
      "adminPassword": {
        "type": "SecureString"
      },
      "adminUsername": {
        "type": "String",
        "value": "richeney"
      },
      "dnsLabelPrefix": {
        "type": "String",
        "value": "richeneyvm"
      },
      "ubuntuOSVersion": {
        "type": "String",
        "value": "16.04.0-LTS"
      }
    },
    :
    :
    :
    "provisioningState": "Succeeded",
    "template": null,
    "templateLink": null,
    "timestamp": "2017-12-08T08:33:20.465371+00:00"
  },
  "resourceGroup": "lab2"
}
```

#### Reading multiple outputs

As we saw in the first lab, you could pull out a single output variable, such as the sshCommand, using a simple JMESPATH query:
```bash
sshCommand=$(az group deployment create --name $job --parameters "@$parms" --template-file $template --resource-group $rg --query properties.outputs.sshCommand.value --output tsv)
echo $sshCommand
```

But we have two variables that we want, which is more of a challenge.  We can change the JMESPATH to output an array with both variables in order, and use the output as an input string to the 'read' inbuilt command:
```bash
query='[properties.outputs.hostname.value, properties.outputs.sshCommand.value]'
read hostName sshCommand <<< $(az group deployment create --name $job --parameters "@$parms" --template-file $template --resource-group $rg --query $query --output tsv)
echo "hostName is $hostName"
echo "sshCommand is $sshCommand"
```

This works, but is a little risky when values can include spaces, as indeed the sshCommand does.

Another approach is to output JSON and read that into a variable as multi-line text.  And then we can use jq to run JMESPATH queries against that.  You can install jq on  Ubuntu by typing `sudo get-apt update && sudo apt-get install jq`.  Once that is there then we can do this instead:

```bash
outputs=$(az group deployment create --name $job --parameters "@$parms" --template-file $template --resource-group $rg --query properties.outputs --output tsv)
hostName=$(jq -r .hostname.value <<< $outputs)
sshCommand=$(jq -r .sshCommand.value <<< $outputs)
```

The first line used a JMESPATH query to filter down to the output section of the JSON, which then shortens the jq commands that follow.

However Python and PowerShell are frankly better for natively handling JSON.

Let's look at setting a variable in PowerShell to the full output of the command and then pulling out the required variables in the following commands.

```powershell
$outputs = (New-AzureRmResourceGroupDeployment -Name $job -TemplateParameterFile $parms -TemplateFile $template -ResourceGroupName $rg).Outputs
$hostName = $Outputs.hostname.Value
$sshCommand = $Outputs.sshCommand.Value
```

## Finishing up

If you have been testing out your templates by deploying them then feel free to delete those test resource group(s) as you did in the last lab.

## What's up next

In the next section we will start to use some of the more complex functions that you can make use of in ARM templates.


text:
# react-umeditor-tiny

[![Version](https://img.shields.io/npm/v/react-umeditor.svg)](https://www.npmjs.com/package/react-umeditor)
[![Downloads](https://img.shields.io/npm/dt/react-umeditor.svg)](https://www.npmjs.com/package/react-umeditor)

React Editor like [Umeditor](https://github.com/fex-team/umeditor)

## Install

	npm install react-umeditor --save

## Use

javascript

``` js
var React = require('react');
var Editor = require('react-umeditor');

class App extends React.Component {
	constructor(props){
		super(props);
		this.state = {
			content: ""
		}
	}
	handleChange(content){
		this.setState({
			content: content
		})
	}
	getIcons(){
		var icons = [
			"source | undo redo | bold italic underline strikethrough fontborder emphasis | ",
			"paragraph fontfamily fontsize | superscript subscript | ",
			"forecolor backcolor | removeformat | insertorderedlist insertunorderedlist | selectall | ",
			"cleardoc  | indent outdent | justifyleft justifycenter justifyright | touppercase tolowercase | ",
			"horizontal date time  | image emotion spechars | inserttable"
		]
		return icons;
	}
	getPlugins(){
		return {
			"image": {
				"uploader": {
					"name":"file",
					"url": "/api/upload"
				}
			}
		}
	}
	render(){
	    var icons = this.getIcons();
		var plugins = this.getPlugins();
		return (<Editor ref="editor"
			icons={icons}
			value={this.state.content} defaultValue="<p>React Umeditor</p>"
			onChange={this.handleChange.bind(this)}
			plugins={plugins} />)
	}
}
```

html

``` html
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Editor Demo</title>

	<!-- mathquill & umeditor stylesheet & if you have the formula icon -->
	<link rel="stylesheet" href="../../dist/third-part/mathquill/mathquill.css"/>

	<link rel="stylesheet" href="app.css" type="text/css" />
</head>
<body>
	<div id="react-container"></div>

	<!-- jquery & mathquill javascript & if you have the formula icon -->
	<script src="../../dist/third-part/jquery.min.js"></script>
	<script src="../../dist/third-part/mathquill/mathquill.js"></script>

	<!-- your react script -->
	<script src="bundle.js"></script>
	<script src="app.js"></script>
</body>
</html>
```

## Example

- [react-umeditor-example](https://github.com/liuhong1happy/react-umeditor-example)

## Ref Functions

You can `this.refs.editor.xxx()`! The `xxx` maybe is as follows:

* findDOMNode: find  refs by ref name  `"root","editarea","toolbar","color" `
* setContent: set html of editor
* getContent: get html of editor
* focusEditor: focus the editor

## Props

You can set the `props`!The `props` maybe is as follows:
* onFocus: the focus event
* onChange: the text change event `{ content: string }`
* defaultValue: default value of editor
* value: value of editor
* icons: icons of toolbar
* plugins: settings of plugins
	* image: settings of image dialog
		* uploader: settings of image uploader
			* name:  form name of xhr
			* url:  url of server
            * type: qiniu or default
            * qiniu: when type is qiniu
                * upload_token: upload_token of qiniu
                * app: app of qiniu
                    * Bucket: Bucket of qiniu
                    * AK: AccessKey of qiniu
                    * SK: SecretKey of qiniu
                * key: resource key of file
                * genKey: when not key,gen resource key of file

## Icons

Support icons, As fllow:

	source undo redo bold italic underline strikethrough fontborder emphasis
	paragraph fontfamily fontsize superscript subscript
	forecolor backcolor removeformat insertorderedlist insertunorderedlist  selectall
	cleardoc  indent outdent justifyleft justifycenter justifyright  touppercase tolowercase
	horizontal date time  image emotion spechars inserttable formula

## Snapshot

![snapshot](editor.png)

## Develop

	// clone code
	git clone https://github.com/liuhong1happy/react-umeditor
	cd react-umeditor
	// install require
	npm install
    npm install envify browserify
    npm install react browserify
    npm install reactify browserify
	// build
	npm run build
	// run example server
	npm run example

## Todo

- [ ] table-edit [wskongdesheng](https://github.com/wskongdesheng)
- [ ] insert time date video audio etc. [liuhong1happy](https://github.com/liuhong1happy)

## Contribute

Changes and improvements are more than welcome! Feel free to fork and open a pull request. Please make your changes in a specific branch and request to pull into master! If you can, please make sure the editor fully works before sending the PR, as that will help speed up the process.

See more [document](https://github.com/liuhong1happy/react-umeditor/blob/master/docs/contribute.md)

## Concat

Email: [liuhong1.happy<EMAIL_ADDRESS>
QQ Group: 247978846

repository: cunyutech/react-umeditor-tiny

repo_name: cunyutech/react-umeditor-tiny


text:
# BayesianModel
This Repository contains three files:

1- A code.py file :
Is written with a python wrapper of a C++ library called " Structural Modeling, Inference and Learning Engine(SMILE) it contains two classes.The fist one is "CreatingBN" for the creation of a Bayesian network that models the causal relationships between metacognitive skills and their influence on the level of self-regulation. The second class is "InferenceCalls" for the modification of the values of each evidence and the  beliefs update (Bayesian inference). It is necessary to import a "pysmile" package from the site https://www.bayesfusion.com/

2- A Network.xdsl file :
Is an xdsl (xml) format file that was built by the CreatingBN class. To view the network, u need just to download the application GeNIe Modeler,GUI for SMILE.

3- A Skills'scores.csv file contains the discretized composite scores for each skill.

repository: sedela/BayesianModel

repo_name: sedela/BayesianModel


text:
# _Haiku Checker_

#### _TDD practice for Epicodus_, _5 Feb. 2020_

#### By _**Michelle Morin, Patrick Kille**_

## Description

_This application checks whether a poem is a haiku._

## Specifications:

| Specification | Example Input | Example Output |
| ------------- |:-------------:| -------------------:|
| Check to see if the poem has three lines | Poem has three lines | True |
| Determines that poem is not haiku if poem does not have exactly 3 lines | poem with 4 lines | "not a haiku" |
| Finds instances of specific strings and replaces the strings with xoxox to maintain correct syllable count | creator | xoxoxor |
| Break each line of poem into individual words | line of poem | array of individual words as each element |
| Subtract all silent vowels | (word)e, y(ellow) | 1, 2 |
| Replace one vowel with "x" for specific double vowel instances | woord | woxrd |
| Insert one consonant ("x") between certain vowel combinations ("io" and "eo") to consider each vowel as a syllable | ion | ixon |
| Count total vowels in each line | Word array | Vowel Count |
| Use count to determine number of syllables in each line | Vowel Count = 2 | Syllables = 2 |
| Returns whether Poem is a Haiku | 5,7,5 syllables | True |

## Setup/Installation Requirements

#### Node install

###### For macOS:
_If Homebrew is not installed on your computer already, then install Homebrew by entering the following two commands in Terminal:_
* $ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
* $ echo 'export PATH=/usr/local/bin:$PATH' >> ~/.bash_profile

_Install Git with the following command:_
* $ brew install git

_Next, install Node.js by entering the following command in Terminal:_
* $ brew install node

###### For Windows:
_Please visit the [Node.js website](https://nodejs.org/en/download/) for installation instructions._

#### Install this application

_Clone this repository via Terminal:_
* _Navigate to the desktop in Terminal by entering "cd desktop"_
* _Enter: "git clone" followed by the url for this repository._
* _Navigate to the project directory by entering "cd" followed by the name of this repository._
* _Confirm that you have navigated to the project directory by entering "pwd" in the Terminal._

_Next, install npm at the project's root directory_
* _Enter the command "npm install"_
* _Enter the command "npm run build"_

_Open the contents of the directory in a text editor or IDE of your choice (e.g., to open the contents of the directory in Visual Studio Code, enter the command "code ." in the Terminal)._

## Known Bugs

_The wordReplacer function currently handles select edge cases, but can be expanded to handle additional. Please submit a pull request if you find another edge case to add!_

## Technologies Used

_Git, HTML, CSS, JavaScript, jQuery, npm, webpack, Jest_

### License

*This webpage is licensed under the MIT license.*

Copyright (c) 2020 **_Michelle Morin, Patrick Kille_**

repository: PRKille/Haiku-Check

repo_name: PRKille/Haiku-Check


text:
---
title: "MCollective » Deploy » Install MCollective"
layout: default
---

[pe_orchestration]: /pe/latest/orchestration_overview.html
[pe_install]: /pe/latest/install_basic.html
[mco_tags]: https://github.com/puppetlabs/marionette-collective/tags
[git_repo]: https://github.com/puppetlabs/marionette-collective
[rakefile]: https://github.com/puppetlabs/marionette-collective/blob/master/Rakefile
[17804]: http://projects.puppetlabs.com/issues/17804
[server_config_best_practices]: /mcollective/configure/server.html#best-practices
[init_lsb]: https://github.com/puppetlabs/marionette-collective/blob/master/mcollective.init
[init_debian]: https://github.com/puppetlabs/marionette-collective/blob/master/ext/debian/mcollective.init
[init_redhat]: https://github.com/puppetlabs/marionette-collective/blob/master/ext/redhat/mcollective.init
[standard]: ./standard.html
[middleware]: ./middleware/
[activemq_connector]: /mcollective/reference/plugins/connector_activemq.html
[activemq_port_config]: /mcollective/deploy/middleware/activemq.html#transport-connectors
[config_server]: /mcollective/configure/server.html
[config_client]: /mcollective/configure/client.html
[deploy_plugins]: ./plugins.html
[anchor_official]: #installing-with-the-official-packages
[enable_repos]: /guides/puppetlabs_package_repositories.html
[server_libdir]: /mcollective/configure/server.html#platform-defaults
[client_libdir]: /mcollective/configure/client.html#platform-defaults
[deploy]: ./index.html

Summary
-----

> **Note:** This page is about installing MCollective. Installation is only one step of a many-step deployment process. See the [MCollective deployment index][deploy] for the complete picture.

> ### Puppet Enterprise
>
> Puppet Enterprise includes MCollective, and automates the entire deployment process. See [the PE orchestration documentation][pe_orchestration] for more details; see [the PE installation instructions][pe_install] to install PE.
>
> * Puppet Enterprise 3.0 ships with MCollective 2.2.4.
> * Puppet Enterprise 2.8 ships with MCollective 1.2.1.

Installing MCollective requires the following steps:

- [Make sure your middleware is up and running and your firewalls are in order.](#pre-install)
- Install the `mcollective` package on servers, then make sure the `mcollective` service is running.
- Install the `mcollective-client` package on admin workstations.
- Most Debian-like and Red Hat-like systems can [use the official Puppet Labs packages](#installing-with-the-official-packages). Enable the Puppet Labs repos, or import the packages into your own repos.
    - If you're on Debian/Ubuntu, [mind the missing package dependency.](#install-stomp-gem-debianubuntu)
- If your systems can't use the official packages, [check the system requirements](#system-requirements) and either [build your own](#rolling-custom-rpm-and-deb-packages) or [run from source](#running-from-source).

### Best Practices

Use site-wide configuration management software to install and configure MCollective. Since you'll need to install the server daemon on every node in your deployment, and since you'll want each node to be running the same version, you should generally use Puppet or something like it to install MCollective.

### Version Notes

MCollective uses a three-part "x.y.z" version number.

* The first digit doesn't have a particularly strict definition, but generally increments for major architectural breaks and incompatibilities.
* The second digit indicates whether this is a stable release: **even** numbers are stable and production-ready, and **odd** numbers are unstable development branches in which breaking changes may happen in minor point releases.
* The third digit reperesents the minor point release; in a stable version series, these should only contain bugfixes, and in an unstable series they may contain anything.

* * *

Pre-Install
-----

* Your [middleware system should be deployed][middleware] before installing MCollective.
* Make sure each server's firewall will allow MCollective to initiate connections with the middleware server. The port depends on your deployment plan; with the recommended [ActiveMQ connector][activemq_connector], this will usually be either 61614 for Stomp/TLS (recommended) or 61613 for unencrypted Stomp, depending on [how you configured ActiveMQ's transport connectors][activemq_port_config].

{% capture postinstall %}[configure the server daemon][config_server], [configure admin workstations][config_client], and [deploy plugins][deploy_plugins]. See the [standard deployment getting started guide][standard] for details.{% endcapture %}

([↑ Back to top](#content))

* * *

System Requirements
-----

MCollective can run on almost any \*nix operating system, as well as Microsoft Windows. It requires one of the following Ruby versions:

* 1.9.3
* 1.8.7

Ruby 2 is not officially supported yet, but may work fine. Ruby 1.8.5 can't use TLS when connecting to the middleware, but works fine over unencrypted connections. Ruby 1.8.6 has the same problem as 1.8.5, and somewhat less automated test coverage. Ruby 1.9.0 through 1.9.2 are NOT supported, and are expected to fail.

MCollective also requires the Stomp rubygem, version **1.2.2 or higher.** The instructions below will note when this has to be handled manually.

### Official Packages

Puppet Labs provides official pre-built packages for the most common Linux-based operating systems. If you are running any of these systems, you can use the "[Official Packages][anchor_official]" install instructions.

#### Red Hat Enterprise Linux (and Derivatives)

{% include platforms_redhat_like.markdown %}

#### Fedora

{% include platforms_fedora.markdown %}

#### Debian-Like

{% include platforms_debian_like.markdown %}

([↑ Back to top](#content))

* * *

Installing With the Official Packages
-----

### Install Stomp Gem (Debian/Ubuntu)

The current MCollective packages for Debian and Ubuntu have a missing dependency on the Stomp gem ([issue 17804][17804]). Before installing MCollective, you must install version **1.2.2 or higher** of the Stomp rubygem. Use one of the following, making sure to check the version:

* The distro's `libstomp-ruby` package (older releases)
* The distro's `ruby-stomp` package (newer releases)
* The `stomp` gem

### Enable Repos or Add Packages

To use the official packages, you must first either [enable the Puppet Labs package repositories][enable_repos] on all systems, or import the following packages from our repo into your local repo:

* `mcollective`
* `mcollective-client`
* `mcollective-common`
* `rubygem-stomp` (on Enterprise Linux variants)

### Install MCollective

* On server nodes, install the `mcollective` package.
* On admin workstations, install the `mcollective-client` package.

Both of these packages install `mcollective-common` as a dependency.

### Enable the MCollective Service

Ensure that the `mcollective` service is running and is enabled to start at boot. The `mcollective` package installs an init script that works with your system's normal service tools.

### Done

At this point, MCollective is installed and running, but cannot connect to the middleware, accept commands, or execute any actions. You should now {{ postinstall }}

### Example

As mentioned [above](#best-practices) and [in the server config reference][server_config_best_practices], you should use Puppet or some other configuration management software to deploy MCollective on your server nodes. This can be done with a simple or modified package/file/service pattern.

The example below uses a modified pattern. It assumes:

* You are [managing settings as resources][server_config_best_practices] in a different class.
* You are maintaining your own package repository with pre-tested versions of the MCollective packages, allowing `ensure => latest` to be used safely. All servers were deployed with this local repository enabled.
* You are managing client workstations separately, and only automating deployment on your server nodes.

{% highlight ruby %}
    class mcollective {
      # Manage Stomp gem dependency on Debian/Ubuntu
      package {'stomp':
        ensure   => '1.2.2',
        provider => gem,
        before   => Package['mcollective'],
      }

      # Install
      package {'mcollective':
        ensure => latest,
      }
      # Run
      service {'mcollective':
        ensure  => running,
        enable  => true,
        require => Package['mcollective'],
      }

      # Restart the service when any settings change
      # (see http://docs.puppetlabs.com/puppet/latest/reference/lang_collectors.html and
      # http://docs.puppetlabs.com/puppet/latest/reference/lang_relationships.html#chaining-arrows
      # for syntax details)
      Package['mcollective'] -> Mcollective::Setting <| |> ~> Service['mcollective']
    }
{% endhighlight %}

([↑ Back to top](#content))

* * *

Rolling Custom RPM and Deb Packages
-----

If you use an RPM-based or deb-based Linux distribution not supported by the official Puppet Labs packages, you can build your own packages with the same automated tooling Puppet Labs uses.

More detailed instructions on this are forthcoming; for the time being, [obtain a copy of the source][mco_tags] and do a quick read-through of the [Rakefile][]. The relevant tasks are named `deb` and `rpm`.

Once you have packages, they will behave much like the official ones; follow the [same instructions above.](#installing-with-the-official-packages)

([↑ Back to top](#content))

* * *

Running From Source
-----

On platforms not supported by the official packages or the underlying RPM and deb tooling, you can run MCollective directly from source.

### Obtain Source

Get a copy of the MCollective source, either by cloning [the GitHub repo][git_repo] or [downloading a tarball][mco_tags].

### Install Ruby and the Stomp Gem

Make sure Ruby is installed and that your system's Ruby version meets [MCollective's system requirements](#system-requirements).

Install **version 1.2.2 or higher** of the `stomp` rubygem.

### Add `mcollective/lib` to Ruby's Load Path

Ruby must be able to load the contents of the `lib` directory in the MCollective source. There are two main ways to do this:

* Recursively copy the contents of `lib` into the `site_ruby` directory
* Put the MCollective source somewhere like `/opt` and use the `RUBYLIB` environment variable to add it to Ruby's load path.

### Put `mcollective/plugins` Somewhere Sensible

MCollective ships with a set of plugins it requires for basic functionality; these do not live in its normal lib path, but in an external directory specified by the `libdir` setting in MCollective's [server][server_libdir] and [client][client_libdir] config files.

You should copy the contents of this `plugins` directory to some platform-appropriate place; **remember the location** for your post-install configuration, since you need to specify it in the `libdir` setting. Red Hat-like platforms put plugins in `/usr/libexec/mcollective`. Debian-like platforms put it in `/usr/share/mcollective/plugins`. Your platform may have its own conventions.

> **Note:** MCollective expects its `libdir` to contain a single directory named `mcollective`, which then contains the rest of the plugin directories. Be sure to not accidentally put your plugins in the directory _above_ the one MCollective will look in.
>
> **Example:**
>
>     # /etc/mcollective/server.cfg
>     # ...
>     libdir = /usr/libexec/mcollective
>
> * Good: `/usr/libexec/mcollective/mcollective/agent/discovery.rb`
> * Bad: `/usr/libexec/mcollective/agent/discovery.rb` (This would only work if you had set a `libdir` of `/usr/libexec`.)

### Add `mcollective/bin` to the Path

The root user on each server node must be able to execute the `mcollectived` binary. Admin users must be able to execute the `mco` binary. You should either copy these to someplace like `/usr/local/bin` and `/usr/local/sbin`, or add the directory they live in to the appropriate users' `PATH` environment variable.

### Roll Your Own Init Script

There are several example init scripts in the MCollective source:

* [A basic LSB-compliant init script][init_lsb]
* [A Red Hat-like init script][init_redhat]
* [A Debian-like init script][init_debian]

There may be other helpful files for your platform in the `mcollective/ext` directory. Use some combination of these to make a platform-appropriate init script for the MCollective server daemon.

### Done

At this point, MCollective is installed and running, but cannot connect to the middleware, accept commands, or execute any actions. You should now {{ postinstall }}

Unlike with the official packages, you won't be able to count on sensible defaults for the config files, so take special note of the logging settings and `libdir` setting.

([↑ Back to top](#content))

* * *

Installing on Windows
-----

We currently have no instructions for installing MCollective on Windows. You should investigate the `ext/windows` directory in the MCollective source. If you've used MCollective on Windows, we'd love to hear about your experience, especially any unexpected pitfalls you ran into. Email<EMAIL_ADDRESS>

repository: richardc/marionette-collective

gha_language: Ruby

repo_name: richardc/marionette-collective


text:
# Db2 Ansible playbooks

The following Db2 Ansible playbooks demonstrate how to prompt registered instantiable applications[^1], Db2 subsystems and create new instances of an application by exploiting IBM Db2 DevOps Experience for z/OS (DOE) APIs.

## Db2 DevOps Experience

The IBM Db2 DevOps Experience (DOE) delivers Db2 for z/OS DBaaS as an integrated set of features. This technology enables a development team to implement DevOps practices by automating and standardizing tasks that would normally require interactions with an operations team. Therefore, it helps bridge the gap between application developers and database administrators.

It provides collaborations between roles in an organization in the following practices:
- Developers can easily provision a version of an application, make changes, test, and promote those changes for approval.
- Quality Engineers can easily automate the creation of Db2 test environments to speed and improve testing activities.
- Administrators can set the site rules for Db2 schema standards and usage rules, review, and approve changes.

These practices decrease development time, improve quality, and better integrate into multi-platform development practices.

## DOE APIs

The services and capabilities of the Db2 DevOps Experience can be used through a browser-based interface called the IBM Unified Experience for z/OS or by scripting the REST APIs.

DOE provides a rich set of REST APIs that provide all of the functions that you need to drive Db2 for z/OS schema changes. The sample playbooks are examples of how DOE APIs can be embedded in any scripting language.

You can access the Swagger API documentation by browsing https://<*host*>:<*port*>/ws/swagger-ui.html where <*host*> is the DNS name or IP address
of the z/OS system where you installed DOE and <*port*> is the port number that you specified for Swagger (12023 by default).

For more information: [Integrating Db2 for z/OS database changes into a CI/CD pipeline](https://www.redbooks.ibm.com/Redbooks.nsf/RedpieceAbstracts/redp5646.html?Open)

## Playbooks Summary
* [**Provision**](db2_provisioning/db2-schema-provision.yml) - Provision a Db2 schema instance of an application
* [**Deprovision**](db2_provisioning/db2-schema-deprovision.yml) - Deprovision a Db2 schema instance of an application
* [**Discovery of Db2 applications**](db2_applications/db2-discover-applications.yml) - Prompt all registered "applications" that can be instantiated
* [**Discovery of Db2 system information**](db2_discovery/db2-discover-subsystems.yml) - Prompt the information on all registered Db2 systems

## Requirements:
* IBM Unified Management Server for V<IP_ADDRESS> or later
* IBM Db2 DevOps Experience for z/OS V<IP_ADDRESS> or later
* Ansible 2.9 or later
## Changelog
All changes are maintained chronologically by date found in the changelog.yml associated with each sample.

# Copyright

© Copyright IBM Corporation 2021

# License

Licensed under [Apache License,
Version 2.0](https://opensource.org/licenses/Apache-2.0)

# Support

Please refer to the [support section](https://github.com/IBM/z_ansible_collections_samples/blob/master/README.md#support) for more
details.

### Note:
[^1]: An application in DOE is a set of objects, such as tablespaces, tables, and indexes that are grouped to be managed and provisioned as a single unit for the use of an application program or a set of application programs.


text:
# vlang-experiments

Just fooling around with a new language. No need to follow.

Eventually this should be a web service, running
in a Docker container, orchestrated by docker-compose.
That's always my first target :smiley:

## What I did (2021-03-23)

I've tried this on an Apple M1:

* `brew install vlang` (0.2.2 46cdf4f)
* Installing "V 0.1.7" plugin for Visual Studio Code
* Try Vex framework, abort because of errors
* Try builtin `vweb` framework, works

## Preliminary verdict

Everything is in earliest stages. I tried the [Vex](https://github.com/nedpals/vex)
web framefork, and it got me a compile error in a context library on the "simple"
example from the examples directory.

This is all to be expected. The language is very
interesting though. The idea of using automatic
deallocation where possible, and automatic reference
counting in all other cases, sounds promising, but
it is also responsible for the somewhat awkward fact
of having no globals.

In a way, V is purer than Go, and you pay the price of
having to structure your program after the language's
will, just like in Rust.

Let's see what comes out of it.

repository: amanessinger/vlang-experiments

repo_name: amanessinger/vlang-experiments


text:
# Calculus

## Articles

- [Calculus Explained with pics and gifs](https://0a.io/chapter1/calculus-explained.html)

repository: lucasczpnk/portfolio

repo_name: lucasczpnk/portfolio


text:
---
title: Mock verification in Kotlin using MockK and Atrium
date: "2019-05-27"
layout: post
path: "/mock-verification-in-kotlin/"
categories:
  - Kotlin
  - Testing
  - MockK
  - SpringBoot
  - Atrium
related:
  - /kotlin-either-types-instead-of-exceptions/
  - /painless-json-with-kotlin-and-jackson/
  - /descriptive-assertions-in-kotlin/
draft: false
description: "When working with Kotlin you might need to build some non trivial mocks that need to be verified. Here is how to do it by combining MockK and Atrium"
---

I have been working with [Kotlin](https://kotlinlang.org/) a lot lately. It is a really awesome language. Elegant, powerful and succinct, it fixes most of the annoyances that I had with _Java_, yet it keeps a certain amount of familiarity that allows the transition from it to be very manageable.

Anyhow, I found myself recently having to build a filter in [SpringBoot](https://spring.io/) that I wanted to test. For that I needed to use both a mock and verify that behavior at the same time. _Kotlin_ is evolving quite fast and there are plenty of alternatives to choose from. I will show how to do this with two excellent libraries, [MockK](https://mockk.io/), and [Atrium](https://docs.atriumlib.org/).

<!--more-->

## MockK and Atrium, a powerful combo

In the short time that I have been developing _Kotlin_, I've noticed a pattern. Whenever you need something not provided in the standard library, you tend to start by using the existing _Java_ library that you are familiar with. Then, at some point, you figure out there is a native _Kotlin_ library that leverages the features from the language better.

[MockK](https://www.thoughtworks.com/radar/languages-and-frameworks/mockk) seems to be on its way to become the defacto mocking library for _Kotlin_ apps. With a syntax based heavily around lambdas, it just looks like a DSL, as you can see in this example taken directly from their page:

```kotlin
val car = mockk<Car>()

every { car.drive(Direction.NORTH) } returns Outcome.OK
car.drive(Direction.NORTH) // returns OK

verify { car.drive(Direction.NORTH) }
```

Meanwhile, _Atrium_ is less established, but after getting the recommendation from a colleague, I gave it a try. It uses `expect`, so for somebody like me who is used to _RSpec_ it is already a win. Anyhow, the syntax takes some time to get used to, but it can be quite expressive. I particularly like combining it with data classes to have exactly one assertion per test instead of many.

## The problem at hand

What I was trying to build was not particularly complex. I wanted to write a filter for a _SpringBoot_ application that would inject some headers into the request based on some logic. All controllers would use these values transparently, without having to care about the computation. The filter looks like this.

```kotlin
@Component
class Filter : OncePerRequestFilter() {
    @Autowired
    lateinit var processor: Processor

    override fun doFilterInternal(request: HttpServletRequest, response: HttpServletResponse, filterChain: FilterChain) {
        val wrappedRequest = HttpServletRequestWrapper(request).apply {
            addHeader(Headers.EXTRA_HEADER, processor.process(request))
        }

        filterChain.doFilter(wrappedRequest, response)
    }
}
```

I want to test two things:

- The `filterChain` should be called with my `wrappedRequest`
- The `wrappedRequest` should have the correct header in it

### Setting up the test

I am using [JUnit 5](https://junit.org/junit5/) for the test (Speaking of native libraries, I haven't tried something like [Spock](https://dzone.com/articles/testing-kotlin-with-spock-part-1-object) yet). The basic setup of the test requires to set up the filter and the mocks that I need.

```kotlin
@ExtendWith(MockKExtension::class)
internal class FilterTest {
    val request = MockHttpServletRequest()

    @MockK
    lateinit var response: HttpServletResponse

    @RelaxedMockK
    lateinit var filterChain: FilterChain

    val filter = Filter().apply {
        processor = ProcessorImpl()
    }
}
```

I am using annotations to initialize the mocks (which requires annotating the test with `MockKExtension`). My `filterChain` is a `RelaxedMockK`, which means that its methods will return a default value unless otherwise specified.

### A very simple test

If I just want to check that the method is being called, I don't really need much

```kotlin
@Test
fun `calls the next step in the filter`() {
    filter.doFilter(request, response, filterChain)
    verify { filterChain.doFilter(any(), response) }
}
```

### Testing the wrapped request

The previous test is OK, but it is a bit bland for my taste. I want to make sure that that the `filterChain` is being called with my `wrappedRequest`, and that it contains the header I injected. This test becomes much more interesting

```kotlin
@Test
fun `injects header into the request and passes it to the filter`() {
    filter.doFilter(request, response, filterChain)

    slot<ServletRequest>().let { slot ->
        verify { filterChain.doFilter(capture(slot), response) }

        expect(slot.captured).isA<HttpServletRequestWrapper> {
            expect(subject.getHeader(Headers.EXTRA_HEADER)).toBe("value")
        }
    }
}
```

Not so simple anymore! Let's break it down.

First we are capturing the first argument for `doFilter` (i.e: the wrapped request). We are creating a new slot by doing `slot<ServletRequest>`, and capturing it by passing it in the `verify` block by doing `capture(slot)`. The `let` block wrapping everything is there so that we don't need an extra local variable (and to feel more kotlin-y inside).

After all this `slot.captured` contains the `wrappedRequest` that we created in the filter. Here is where _Atrium_ can shine. We use `isA` first to check that the request is of the right type. Then inside the block `subject` is the casted type, where we finally check that our header is there.

## Summary

With this our small filter can be tested properly and with very little overhead. I am no _Kotlin_ connoisseur, but the syntax of both _MockK_ and _Atrium_ feels quite elegant to me, once you wrap your head around it. I think this is a good starting point to build better and better tests without a ton of boilerplate code.


text:
---
layout: blog
title: "NDT Dataset - 2 Billion Rows and Growing"
author: "Chris Ritzo"
date: 2019-09-18
breadcrumb: blog
categories:
  - data
---

While we've been hard at work this year on the [M-Lab 2.0 Platform Upgrade]({{ site.baseurl }}/blog/) and [Global Pilot]({{ site.baseurl }}/blog/), the number of people all over the world runing NDT tests has continued to grow. We collected 2 billion total NDT results between 2009-01-01 and the beginning of the second quarter of 2019, and we are on track to add 500 million just from April through September of this year! We now regularly exceed 3 million NDT tests per day, compared with 2.4 million per day at the end of the first quarter of 2019, 1 million per day two years ago, and 50k per day four years ago.<!--more-->

It took us 6 years to get our first 500 million rows, and we now receive that many measurements every 6 months!

Our data scale has grown exponentially, our usage has grown tremendously, and our platform keep chugging along. We now regularly serve more than 3 million NDT tests a day worldwide! To break that down a little further, we've compiled the table below showing the number of tests per country from Jan 1 - June 30, 2019.

Thanks to all of our users around the world for using M-Lab!!

| Number of Tests Jan-Jun 2019  | Country |
|:------------------------|:-------|
| 8746 | Afghanistan |
| 28550 | Albania |
| 180976 | Algeria |
| 515 | American Samoa |
| 8621 | Andorra |
| 12932 | Angola |
| 316 | Anguilla |
| 4058 | Antigua and Barbuda |
| 426821 | Argentina |
| 12607 | Armenia |
| 7563 | Aruba |
| 16632689 | Australia |
| 2532621 | Austria |
| 36826 | Azerbaijan |
| 13881 | Bahamas |
| 19203 | Bahrain |
| 224918 | Bangladesh |
| 8486 | Barbados |
| 91965 | Belarus |
| 1807273 | Belgium |
| 9567 | Belize |
| 1943 | Benin |
| 12606 | Bermuda |
| 67 | Bhutan |
| 95890 | Bolivia |
| 763 | Bonaire, Sint Eustatius, and Saba |
| 72540 | Bosnia and Herzegovina |
| 3448 | Botswana |
| 7296632 | Brazil |
| 47 | British Indian Ocean Territory |
| 1562 | British Virgin Islands |
| 7734 | Brunei |
| 97284 | Bulgaria |
| 4077 | Burkina Faso |
| 1034 | Burundi |
| 1720 | Cabo Verde |
| 22534 | Cambodia |
| 6791 | Cameroon |
| 12904120 | Canada |
| 10385 | Cayman Islands |
| 47 | Central African Republic |
| 156 | Chad |
| 142953 | Chile |
| 305630 | China |
| 61 | Christmas Island |
| 170 | Cocos [Keeling] Islands |
| 632599 | Colombia |
| 507 | Comoros |
| 2330 | Congo |
| 30 | Cook Islands |
| 102188 | Costa Rica |
| 96966 | Croatia |
| 535 | Cuba |
| 9243 | Curaﺃao |
| 224130 | Cyprus |
| 1137009 | Czechia |
| 709 | Democratic Republic of Timor-Leste |
| 348134 | Denmark |
| 2224 | Djibouti |
| 898 | Dominica |
| 126461 | Dominican Republic |
| 352821 | Ecuador |
| 613332 | Egypt |
| 72729 | El Salvador |
| 635 | Equatorial Guinea |
| 63 | Eritrea |
| 38318 | Estonia |
| 1326 | Eswatini |
| 21941 | Ethiopia |
| 20 | Falkland Islands |
| 214 | Faroe Islands |
| 296 | Federated States of Micronesia |
| 2141 | Fiji |
| 129254 | Finland |
| 6205621 | France |
| 3731 | French Guiana |
| 3771 | French Polynesia |
| 3139 | Gabon |
| 1046 | Gambia |
| 25003 | Georgia |
| 20940419 | Germany |
| 112103 | Ghana |
| 1680 | Gibraltar |
| 285073 | Greece |
| 1733 | Greenland |
| 1582 | Grenada |
| 5633 | Guadeloupe |
| 3274 | Guam |
| 100441 | Guatemala |
| 5596 | Guernsey |
| 12777 | Guinea |
| 253 | Guinea-Bissau |
| 9347 | Guyana |
| 6314 | Haiti |
| 49168 | Hashemite Kingdom of Jordan |
| 78783 | Honduras |
| 197754 | Hong Kong |
| 379576 | Hungary |
| 22097 | Iceland |
| 1746883 | India |
| 9104425 | Indonesia |
| 7137 | Iran |
| 211894 | Iraq |
| 2362946 | Ireland |
| 13396 | Isle of Man |
| 183298 | Israel |
| 19528272 | Italy |
| 7201 | Ivory Coast |
| 27795 | Jamaica |
| 6923812 | Japan |
| 27084 | Jersey |
| 69697 | Kazakhstan |
| 829093 | Kenya |
| 32 | Kiribati |
| 4436 | Kosovo |
| 42573 | Kuwait |
| 11246 | Kyrgyzstan |
| 6933 | Laos |
| 39639 | Latvia |
| 105054 | Lebanon |
| 132 | Lesotho |
| 2103 | Liberia |
| 37529 | Libya |
| 4058 | Liechtenstein |
| 45017 | Luxembourg |
| 81990 | Macao |
| 20798 | Macedonia |
| 58284 | Madagascar |
| 1563 | Malawi |
| 164617 | Malaysia |
| 9263 | Maldives |
| 3584 | Mali |
| 15405 | Malta |
| 572 | Marshall Islands |
| 4259 | Martinique |
| 3461 | Mauritania |
| 20936 | Mauritius |
| 1291 | Mayotte |
| 1661953 | Mexico |
| 6069 | Monaco |
| 2701 | Mongolia |
| 25691 | Montenegro |
| 167 | Montserrat |
| 1492192 | Morocco |
| 52623 | Mozambique |
| 24369 | Myanmar |
| 6462 | Namibia |
| 11 | Nauru |
| 137433 | Nepal |
| 4098810 | Netherlands |
| 4467 | New Caledonia |
| 1598579 | New Zealand |
| 57602 | Nicaragua |
| 1871 | Niger |
| 215105 | Nigeria |
| 131 | Niue |
| 11 | Norfolk Island |
| 13027 | North Macedonia |
| 158 | Northern Mariana Islands |
| 826926 | Norway |
| 43116 | Oman |
| 196311 | Pakistan |
| 191 | Palau |
| 25968 | Palestine |
| 56976 | Panama |
| 1094 | Papua New Guinea |
| 30396 | Paraguay |
| 149744 | Peru |
| 9699182 | Philippines |
| 445818 | Poland |
| 2320824 | Portugal |
| 97530 | Puerto Rico |
| 36891 | Qatar |
| 59598 | Republic of Lithuania |
| 25165 | Republic of Moldova |
| 619 | Republic of the Congo |
| 192155 | Romania |
| 1726912 | Russia |
| 2150 | Rwanda |
| 7004 | Rﺃﺏunion |
| 1201 | Saint Barthﺃﺏlemy |
| 1831 | Saint Lucia |
| 2341 | Saint Martin |
| 88 | Saint Pierre and Miquelon |
| 833 | Saint Vincent and the Grenadines |
| 144 | Samoa |
| 344 | San Marino |
| 244623 | Saudi Arabia |
| 9115 | Senegal |
| 1776274 | Serbia |
| 2023 | Seychelles |
| 1980 | Sierra Leone |
| 1501853 | Singapore |
| 2190 | Sint Maarten |
| 191418 | Slovakia |
| 70471 | Slovenia |
| 161 | Solomon Islands |
| 7273 | Somalia |
| 5092969 | South Africa |
| 5 | South Georgia and the South Sandwich Islands |
| 212622 | South Korea |
| 228 | South Sudan |
| 11522800 | Spain |
| 22374 | Sri Lanka |
| 1013 | St Kitts and Nevis |
| 684 | Sudan |
| 5358 | Suriname |
| 979473 | Sweden |
| 628667 | Switzerland |
| 3914 | Syria |
| 2105 | Sﺃ£o Tomﺃﺏ and Prﺃﺝncipe |
| 222844 | Taiwan |
| 2538 | Tajikistan |
| 51643 | Tanzania |
| 4518301 | Thailand |
| 2408 | Togo |
| 12 | Tokelau |
| 82 | Tonga |
| 17954 | Trinidad and Tobago |
| 846596 | Tunisia |
| 451622 | Turkey |
| 2346 | Turkmenistan |
| 2113 | Turks and Caicos Islands |
| 7 | Tuvalu |
| 4587 | U.S. Virgin Islands |
| 57340 | Uganda |
| 450214 | Ukraine |
| 249877 | United Arab Emirates |
| 28500362 | United Kingdom |
| 134569463 | United States |
| 30699 | Uruguay |
| 31571 | Uzbekistan |
| 1421 | Vanuatu |
| 373 | Vatican City |
| 90792 | Venezuela |
| 282759 | Vietnam |
| 28 | Wallis and Futuna |
| 8 | Western Sahara |
| 40232 | Yemen |
| 4219 | Zambia |
| 6226 | Zimbabwe |

repository: FangfanLi/website

repo_name: FangfanLi/website