text:
---
title: "Xzarts"
tags: miniatures
date: 2023-08-17
layout: post
---

![img](./xvart.png)

![Xvarts in BG](./latest.png)

Xvarts are horrible little creatures in D&D. First time I encountered them was in Baldur's Gate. They are nice monsters for a level 1 group and bring some change from the usual kobold / giant rat trope.

![image-20230817170056449](./image-20230817170056449.png)

I wanted to have some myself, so I set out on finding the right miniatures for that. Official Xvart miniatures are way to expensive.

![image-20230817170134008](./image-20230817170134008.png)

I picked those old orcs I had lying in a drawer. They are very tiny scale, as you can see, I fitted them on one cent coins.

![image-20230817170243508](./image-20230817170243508.png)

I painted them blue, and added some very light drybrush on their skin, but painted their clothes in brown shades with a dark wash. The contrast made them distinctive enough for my purpose.

![image-20230817170338843](./image-20230817170338843.png)

I expect them to be living in sewers below a small scale city.


text:
# JSON Spirit: A C++ JSON Parser/Generator Implemented with Boost Spirit

## Introduction

JSON is a text file format similar to XML, but less verbose. It has been called "XML lite". This article describes JSON Spirit, a C++ library that reads and writes JSON files or streams. It is written using the Boost Spirit parser generator. If you are already using Boost, you can use JSON Spirit without any additional dependencies.

## Key features:

supports ASCII or Unicode
std::vector or std::map implementations for JSON Objects
object library or header file only use
Using the Code
The JSON Spirit source code is available as a Microsoft Visual Studio 2005 C++ "solution". However, it should compile and work on any platform compatible with Boost. JSON Spirit has been built and tested with Visual C++ 2005, 2008, 2010, and G++ version 4.2.3 on Linux. It has been tested with Visual C++ using Boost versions 1.34.0, 1.37.0, 1.39.0, and 1.42.0. It has also been tested with STLPort.

Platform independent CMake files are included, kindly supplied by Uwe Arzt, with CPack declarations for packaging and a "make install" target supplied by Amzlkej.

The Visual C++ solution consists of five projects:

- The JSON Spirit library and header files

- An application running the library's unit tests

- Three small programs demonstrating how to use JSON Spirit

## Source

The original location of this code is: https://www.codeproject.com/Articles/20027/JSON-Spirit-A-C-JSON-Parser-Generator-Implemented

# License

The MIT License (MIT)

Copyright (c) 2017 John W. Wilkinson

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

license: MIT

branch_name: refs/heads/master

extension: md

license_type: permissive


text:
It's like laradock but for Magento instead of Laravel.

## Installation

Let's see how easy it is to install `NGINX`, `PHP`, `Composer`, `MySQL` and `Redis`. Then run `Magento`.

1. Get Magedock inside your Magento project:

```bash
git submodule add https://github.com/PaoloFalomo/magedock.git
```
2. Copy local.env.sample to local.env and modify it to your needs.
3. Enter the magedock folder and run only these Containers:

`docker-compose up -d nginx mysql redis`

4. `docker-compose exec workspace magento-installer`
5. Open your browser and visit the localhost: `http://localhost`

repository: PaoloFalomo/magedock

repo_name: PaoloFalomo/magedock


text:
## Definition

To define mappings between a model and a table, use the `define` method. Sequelize will then automatically add the attributes `createdAt` and `updatedAt` to it. So you will be able to know when the database entry went into the db and when it was updated the last time. If you do not want timestamps on your models, only want some timestamps, or you are working with an existing database where the columns are named something else, jump straight on to [configuration ][0]to see how to do that.

```js
var Project = sequelize.define('Project', {
  title: Sequelize.STRING,
  description: Sequelize.TEXT
})

var Task = sequelize.define('Task', {
  title: Sequelize.STRING,
  description: Sequelize.TEXT,
  deadline: Sequelize.DATE
})
```

You can also set some options on each column:

```js
var Foo = sequelize.define('Foo', {
 // instantiating will automatically set the flag to true if not set
 flag: { type: Sequelize.BOOLEAN, allowNull: false, defaultValue: true},

 // default values for dates => current time
 myDate: { type: Sequelize.DATE, defaultValue: Sequelize.NOW },

 // setting allowNull to false will add NOT NULL to the column, which means an error will be
 // thrown from the DB when the query is executed if the column is null. If you want to check that a value
 // is not null before querying the DB, look at the validations section below.
 title: { type: Sequelize.STRING, allowNull: false},

 // Creating two objects with the same value will throw an error. The unique property can be either a
 // boolean, or a string. If you provide the same string for multiple columns, they will form a
 // composite unique key.
 someUnique: {type: Sequelize.STRING, unique: true},
 uniqueOne: { type: Sequelize.STRING,  unique: 'compositeIndex'},
 uniqueTwo: { type: Sequelize.INTEGER, unique: 'compositeIndex'}

 // Go on reading for further information about primary keys
 identifier: { type: Sequelize.STRING, primaryKey: true},

 // autoIncrement can be used to create auto_incrementing integer columns
 incrementMe: { type: Sequelize.INTEGER, autoIncrement: true },

 // Comments can be specified for each field for MySQL and PG
 hasComment: { type: Sequelize.INTEGER, comment: "I'm a comment!" },

 // You can specify a custom field name via the "field" attribute:
 fieldWithUnderscores: { type: Sequelize.STRING, field: "field_with_underscores" }
})
```

The comment option can also be used on a table, see [model configuration][0]

## Data types

Sequelize currently supports the following datatypes:

```js
Sequelize.STRING                      // VARCHAR(255)
Sequelize.STRING(1234)                // VARCHAR(1234)
Sequelize.STRING.BINARY               // VARCHAR BINARY
Sequelize.TEXT                        // TEXT

Sequelize.INTEGER                     // INTEGER
Sequelize.BIGINT                      // BIGINT
Sequelize.BIGINT(11)                  // BIGINT(11)
Sequelize.FLOAT                       // FLOAT
Sequelize.FLOAT(11)                   // FLOAT(11)
Sequelize.FLOAT(11, 12)               // FLOAT(11,12)

Sequelize.DECIMAL                     // DECIMAL
Sequelize.DECIMAL(10, 2)              // DECIMAL(10,2)

Sequelize.DATE                        // DATETIME for mysql / sqlite, TIMESTAMP WITH TIME ZONE for postgres
Sequelize.BOOLEAN                     // TINYINT(1)

Sequelize.ENUM('value 1', 'value 2')  // An ENUM with allowed values 'value 1' and 'value 2'
Sequelize.ARRAY(Sequelize.TEXT)       // Defines an array. PostgreSQL only.

Sequelize.BLOB                        // BLOB (bytea for PostgreSQL)
Sequelize.BLOB('tiny')                // TINYBLOB (bytea for PostgreSQL. Other options are medium and long)
Sequelize.UUID                        // UUID datatype for PostgreSQL and SQLite, CHAR(36) BINARY for MySQL (use defaultValue: Sequelize.UUIDV1 or Sequelize.UUIDV4 to make sequelize generate the ids automatically)
```

The BLOB data type allows you to insert data both as strings and as buffers. When you do a find or findAll on a model which has a BLOB column, that data will always be returned as a buffer.

If you are working with the PostgreSQL TIMESTAMP WITHOUT TIME ZONE and you need to parse it to a different timezone, please use the pg library's own parser:

```js
require('pg').types.setTypeParser(1114, function(stringValue) {
  return new Date(stringValue + "+0000");
  // e.g., UTC offset. Use any offset that you would like.
});
```

In addition to the type mentioned above, integer, bigint and float also support unsigned and zerofill properties, which can be combined in any order:

```js
Sequelize.INTEGER.UNSIGNED              // INTEGER UNSIGNED
Sequelize.INTEGER(11).UNSIGNED          // INTEGER(11) UNSIGNED
Sequelize.INTEGER(11).ZEROFILL          // INTEGER(11) ZEROFILL
Sequelize.INTEGER(11).ZEROFILL.UNSIGNED // INTEGER(11) UNSIGNED ZEROFILL
Sequelize.INTEGER(11).UNSIGNED.ZEROFILL // INTEGER(11) UNSIGNED ZEROFILL
```

_The examples above only show integer, but the same can be done with bigint and float_

Usage in object notation:

```js
// for enums:
sequelize.define('model', {
  states: {
    type:   Sequelize.ENUM,
    values: ['active', 'pending', 'deleted']
  }
})
```

## Getters & setters

It is possible to define 'object-property' getters and setter functions on your models, these can be used both for 'protecting' properties that map to database fields and for defining 'pseudo' properties.

Getters and Setters can be defined in 2 ways (you can mix and match these 2 approaches!):

* as part of a single property definition
* as part of a model options

**N.B.:**If a getter or setter is defined in both places then the function found in the relevant property definition will always take precedence.

### Defining as part of a property

```js
var Foo = sequelize.define('Foo', {
  name: { Sequelize.STRING },
  title: {
    type     : Sequelize.STRING,
    allowNull: false,
    get      : function()  {
       /*
         do your magic here and return something!
         'this' allows you to access attributes of the model.

        example: this.getDataValue('name') works
      */
    },
    set      : function(v) { /* do your magic with the input here! */ }
  }
});
```

### Defining as part of the model options

Below is an example of defining the getters and setters in the model options, notice the `title_slugslug` getter, it shows how you can define `pseudo` properties on your models! (the `slugify()` function was taken from the [Underscore.String module][1], it is slightly modified here so that the example remains self-contained), note that the `this.title` reference in the `title_slug` getter function will trigger a call to the `title` getter function. if you do not want that then use the `getDataValue()` method ([see below][2]).

```js
var defaultToWhiteSpace = function(characters) {
    if (characters == null)
      return '\\s';
    else if (characters.source)
      return characters.source;
    else
      return ;
  };

var slugify = function(str) {
  var from  = "ąàáäâãåæćęèéëêìíïîłńòóöôõøśùúüûñçżź",
      to    = "aaaaaaaaceeeeeiiiilnoooooosuuuunczz",
      regex = new RegExp('[' + from.replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1') + ']', 'g');

  if (str == null) return '';

  str = String(str).toLowerCase().replace(regex, function(c) {
    return to.charAt(from.indexOf(c)) || '-';
  });

  return str.replace(/[^\w\s-]/g, '').replace(/([A-Z])/g, '-$1').replace(/[-_\s]+/g, '-').toLowerCase();
}

var Foo = sequelize.define('Foo', {
  title: {
    type     : Sequelize.STRING,
    allowNull: false,
  }
}, {

  getterMethods   : {
    title       : function()  { /* do your magic here and return something! */ },
    title_slug  : function()  { return slugify(this.title); }
  },

  setterMethods   : {
    title       : function(v) { /* do your magic with the input here! */ },
  }
});
```

### Helper functions for use inside getter/setter definitions

* retrieving an underlying property value? always use `this.getDataValu()`, e.g:

```js
/* a getter for 'title' property */
function() {
    return this.getDataValue('title');
}
```

* setting an underlying property value? always use `this.setDataValue()`, e.g.:

```js
/* a setter for 'title' property */
function(title) {
    return this.setDataValue('title', title.toString().toLowerCase());
}
```

**N.B.: **It is important to stick to using the `setDataValue()` and `getDataValue()` functions (as opposed to accessing the underlying "data values" property directly) - doing so protects your custom getters and setters from changes in the underlying model implementations (i.e. how and where data values are stored in your model instances)

### Setter methods and Object Initialization

!!!TODO: write about how setters affect object initialization (both creating new objects with Model.build and retrieving existing objects from storage) !!!!!

## Validations

Model validations, allow you to specify format/content/inheritance validations for each attribute of the model. You can perform the validation by calling the `validate()` method on an instance before saving. The validations are implemented by [validator][3].

**Note: **In `v1.7.0` validations will now be called when executing the `build()` or `create()` functions.

```js
var ValidateMe = sequelize.define('Foo', {
  foo: {
    type: Sequelize.STRING,
    validate: {
      is: ["^[a-z]+$",'i'],     // will only allow letters
      is: /^[a-z]+$/i,          // same as the previous example using real RegExp
      not: ["[a-z]",'i'],       // will not allow letters
      isEmail: true,            // checks for email format<EMAIL_ADDRESS>      isUrl: true,              // checks for url format (http://foo.com)
      isIP: true,               // checks for IPv4 (<IP_ADDRESS>) or IPv6 format
      isIPv4: true,             // checks for IPv4 (<IP_ADDRESS>)
      isIPv6: true,             // checks for IPv6 format
      isAlpha: true,            // will only allow letters
      isAlphanumeric: true      // will only allow alphanumeric characters, so "_abc" will fail
      isNumeric: true           // will only allow numbers
      isInt: true,              // checks for valid integers
      isFloat: true,            // checks for valid floating point numbers
      isDecimal: true,          // checks for any numbers
      isLowercase: true,        // checks for lowercase
      isUppercase: true,        // checks for uppercase
      notNull: true,            // won't allow null
      isNull: true,             // only allows null
      notEmpty: true,           // don't allow empty strings
      equals: 'specific value', // only allow a specific value
      contains: 'foo',          // force specific substrings
      notIn: [['foo', 'bar']],  // check the value is not one of these
      isIn: [['foo', 'bar']],   // check the value is one of these
      notContains: 'bar',       // don't allow specific substrings
      len: [2,10],              // only allow values with length between 2 and 10
      isUUID: 4,                // only allow uuids
      isDate: true,             // only allow date strings
      isAfter: "2011-11-05",    // only allow date strings after a specific date
      isBefore: "2011-11-05",   // only allow date strings before a specific date
      max: 23,                  // only allow values
      min: 23,                  // only allow values >= 23
      isArray: true,            // only allow arrays
      isCreditCard: true,       // check for valid credit card numbers

      // custom validations are also possible:
      isEven: function(value) {
        if(parseInt(value) % 2 != 0) {
          throw new Error('Only even values are allowed!')
        // we also are in the model's context here, so this.otherField
        // would get the value of otherField if it existed
        }
      }
    }
  }
})
```

Note that where multiple arguments need to be passed to the built-in validation functions, the arguments to be passed must be in an array. But if a single array argument is to be passed, for instance an array of acceptable strings for `isIn`, this will be interpreted as multiple string arguments instead of one array argument. To work around this pass a single-length array of arguments, such as `[['one', 'two']]` as shown above.

To use a custom error message instead of that provided by node-validator, use an object instead of the plain value or array of arguments, for example a validator which needs no argument can be given a custom message with

```js
isInt: {
  msg: "Must be an integer number of pennies"
}
```

or if arguments need to also be passed add an`args`property:

```js
isIn: {
  args: [['en', 'zh']],
  msg: "Must be English or Chinese"
}
```

When using custom validator functions the error message will be whatever message the thrown`Error`object holds.

See [the node-validator project][4]for more details on the built in validation methods.

**Hint: **You can also define a custom function for the logging part. Just pass a function. The first parameter will be the string that is logged.

### Validators and`allowNull`

Since `v1.7.0` if a particular field of a model is set to allow null (with `allowNull: true`) and that value has been set to `null` , its validators do not run. This means you can, for instance, have a string field which validates its length to be at least 5 characters, but which also allows`null`.

### Model validations

Since `v1.7.0` , validations can also be defined to check the model after the field-specific validators. Using this you could, for example, ensure either neither of `latitude` and `longitude` are set or both, and fail if one but not the other is set.

Model validator methods are called with the model object's context and are deemed to fail if they throw an error, otherwise pass. This is just the same as with custom field-specific validators.

Any error messages collected are put in the validation result object alongside the field validation errors, with keys named after the failed validation method's key in the `validate` option object. Even though there can only be one error message for each model validation method at any one time, it is presented as a single string error in an array, to maximize consistency with the field errors. (Note that the structure of `validate()`'s output is scheduled to change in `v2.0`to avoid this awkward situation. In the mean time, an error is issued if a field exists with the same name as a custom model validation.)

An example:

```js
var Pub = Sequelize.define('Pub', {
  name: { type: Sequelize.STRING },
  address: { type: Sequelize.STRING },
  latitude: {
    type: Sequelize.INTEGER,
    allowNull: true,
    defaultValue: null,
    validate: { min: -90, max: 90 }
  },
  longitude: {
    type: Sequelize.INTEGER,
    allowNull: true,
    defaultValue: null,
    validate: { min: -180, max: 180 }
  },
}, {
  validate: {
    bothCoordsOrNone: function() {
      if ((this.latitude === null) === (this.longitude === null)) {
        throw new Error('Require either both latitude and longitude or neither')
      }
    }
  }
})
```

In this simple case an object fails validation if either latitude or longitude is given, but not both. If we try to build one with an out-of-range latitude and nolongitude, `raging_bullock_arms.validate()` might return

```js
{
  'latitude': ['Invalid number: latitude'],
  'bothCoordsOrNone': ['Require either both latitude and longitude or neither']
}
```

## Configuration

You can also influence the way Sequelize handles your column names:

```js
var Bar = sequelize.define('Bar', { /* bla */ }, {
  // don't add the timestamp attributes (updatedAt, createdAt)
  timestamps: false,

  // don't delete database entries but set the newly added attribute deletedAt
  // to the current date (when deletion was done). paranoid will only work if
  // timestamps are enabled
  paranoid: true,

  // don't use camelcase for automatically added attributes but underscore style
  // so updatedAt will be updated_at
  underscored: true,

  // disable the modification of tablenames; By default, sequelize will automatically
  // transform all passed model names (first parameter of define) into plural.
  // if you don't want that, set the following
  freezeTableName: true,

  // define the table's name
  tableName: 'my_very_custom_table_name'
})
```

If you want sequelize to handle timestamps, but only want some of them, or want your timestamps to be called something else, you can override each column individually:

```js
var Foo = sequelize.define('Foo',  { /* bla */ }, {
  // don't forget to enable timestamps!
  timestamps: true,

  // I don't want createdAt
  createdAt: false,

  // I want updatedAt to actually be called updateTimestamp
  updatedAt: 'updateTimestamp'

  // And deletedAt to be called destroyTime (remember to enable paranoid for this to work)
  deletedAt: 'destroyTime',
  paranoid: true
})
```

You can also change the database engine, e.g. to MyISAM. InnoDB is the default.

```js
var Person = sequelize.define('Person', { /* attributes */ }, {
  engine: 'MYISAM'
})

// or globally
var sequelize = new Sequelize(db, user, pw, {
  define: { engine: 'MYISAM' }
})
```

Finaly you can specify a comment for the table in MySQL and PG

```js
var Person = sequelize.define('Person', { /* attributes */ }, {
  comment: "I'm a table comment!"
})
```

## Import

You can also store your model definitions in a single file using the `import` method. The returned object is exactly the same as defined in the imported file's function. Since `v1:5.0` of Sequelize the import is cached, so you won't run into troubles when calling the import of a file twice or more often.

```js
// in your server file - e.g. app.js
var Project = sequelize.import(__dirname + "/path/to/models/project")

// The model definition is done in /path/to/models/project.js
// As you might notice, the DataTypes are the very same as explained above
module.exports = function(sequelize, DataTypes) {
  return sequelize.define("Project", {
    name: DataTypes.STRING,
    description: DataTypes.TEXT
  })
}
```

Since `v1.7.0` the `import` method can now accept a callback as an argument.

```js
sequelize.import('Project', function(sequelize, DataTypes) {
  return sequelize.define("Project", {
    name: DataTypes.STRING,
    description: DataTypes.TEXT
  })
})
```

## Database synchronization

When starting a new project you won't have a database structure and using Sequelize you won't need to. Just specify your model structures and let the library do the rest. Currently supported is the creation and deletion of tables:

```js
// Create the tables:
Project.sync() // will emit success or failure event
Task.sync() // will emit success or failure event

// Force the creation!
Project.sync({force: true}) // this will drop the table first and re-create it afterwards

// drop the tables:
Project.drop() // will emit success or failure event
Task.drop() // will emit success or failure event

// event handling:
Project.[sync|drop]().then(function() {
  // ok ... everything is nice!
}).catch(function(error) {
  // oooh, did you entered wrong database credentials?
})
```

Because synchronizing and dropping all of your tables might be a lot of lines to write, you can also let Sequelize do the work for you:

```js
// create all tables... now!
sequelize.sync() // will emit success or failure

// force it!
sequelize.sync({force: true}) // emit ... nomnomnom

// want to drop 'em all?
sequelize.drop() // I guess you've got it (emit)

// emit handling:
sequelize.[sync|drop]().then(function() {
  // woot woot
}).catch(function(error) {
  // whooops
})
```

## Expansion of models

Sequelize allows you to pass custom methods to a model and it's instances. Just do the following:

```js
var Foo = sequelize.define('Foo', { /* attributes */}, {
  classMethods: {
    method1: function(){ return 'smth' }
  },
  instanceMethods: {
    method2: function() { return 'foo' }
  }
})

// Example:
Foo.method1()
Foo.build().method2()
```

Of course you can also access the instance's data and generate virtual getters:

```js
var User = sequelize.define('User', { firstname: Sequelize.STRING, lastname: Sequelize.STRING }, {
  instanceMethods: {
    getFullname: function() {
      return [this.firstname, this.lastname].join(' ')
    }
  }
})

// Example:
User.build({ firstname: 'foo', lastname: 'bar' }).getFullname() // 'foo bar'
```

You can also set custom methods to all of your models during the instantiation:

```js
var sequelize = new Sequelize('database', 'username', 'password', {
  // Other options during the initialization could be here
  define: {
    classMethods: {
      method1: function() {},
      method2: function() {}
    },
    instanceMethods: {
      method3: function() {}
    }
  }
})

// Example:
var Foo = sequelize.define('Foo', { /* attributes */});
Foo.method1()
Foo.method2()
Foo.build().method3()
```

## Data retrieval / Finders

Finder methods are designed to get data from the database. The returned data isn't just a plain object, but instances of one of the defined classes. Check the next major chapter about instances for further information. But as those things are instances, you can e.g. use the just describe expanded instance methods. So, here is what you can do:

### find - Search for one specific element in the database
```js
// search for known ids
Project.find(123).then(function(project) {
  // project will be an instance of Project and stores the content of the table entry
  // with id 123. if such an entry is not defined you will get null
})

// search for attributes
Project.find({ where: {title: 'aProject'} }).then(function(project) {
  // project will be the first entry of the Projects table with the title 'aProject' || null
})

// since v1.3.0: only select some attributes and rename one
Project.find({
  where: {title: 'aProject'},
  attributes: ['id', ['name', 'title']]
}).then(function(project) {
  // project will be the first entry of the Projects table with the title 'aProject' || null
  // project.title will contain the name of the project
})
```

### findOrCreate - Search for a specific element or create it if not available

The method `findOrCreate` can be used to check if a certain element is already existing in the database. If that is the case the method will result in a respective instance. If the element does not yet exist, it will be created.

Let's assume we have an empty database with a `User` model which has a `username` and a `job`.

```js
User
  .findOrCreate({ username: 'sdepold' }, { job: 'Technical Lead JavaScript' })
  .then(function(user, created) {
    console.log(user.values)
    console.log(created)

    /*
      {
        username: 'sdepold',
        job: 'Technical Lead JavaScript',
        id: 1,
        createdAt: Fri Mar 22 2013 21: 28: 34 GMT + 0100(CET),
        updatedAt: Fri Mar 22 2013 21: 28: 34 GMT + 0100(CET)
      }
      created: true
    */
  })
```

The code created a new instance. So when we already have an instance ...
```js
User
  .create({ username: 'fnord', job: 'omnomnom' })
  .then(function() {
    User
      .findOrCreate({ username: 'fnord' }, { job: 'something else' })
      .then(function(user, created) {
        console.log(user.values)
        console.log(created)

        /*
          {
            username: 'fnord',
            job: 'omnomnom',
            id: 2,
            createdAt: Fri Mar 22 2013 21: 28: 34 GMT + 0100(CET),
            updatedAt: Fri Mar 22 2013 21: 28: 34 GMT + 0100(CET)
          }
          created: false
        */
      })
  })
```

... the existing entry will not be changed. See the `job` of the second user, and the fact that created was false.

Notice that the success callback has two arguments. When using [promises][5] you should call `spread` [(API ref)][6] instead of `then`, since `then` will only recieve the first argument (the DAO), while `spread` will recieve both the DAO, and the `created` boolean.

### findAndCountAll - Search for multiple elements in the database, returns both data and total count

This is a convienience method that combines`findAll()`and`count()`(see below), this is useful when dealing with queries related to pagination where you want to retrieve data with a`limit`and`offset`but also need to know the total number of records that match the query.

The success handler will always receive an object with two properties:

* `count` - an integer, total number records (matching the where clause)
* `rows` - an array of objects, the records (matching the where clause) within the limit/offset range
```js
Project
  .findAndCountAll({
     where: {
        title: {
            like: 'foo%'
        }
     },
     offset: 10,
     limit: 2
  })
  .then(function(result) {
    console.log(result.count);
    console.log(result.rows);
  });
```

The options [object] that you pass to`findAndCountAll()`is the same as for`findAll()`(described below).

### findAll - Search for multiple elements in the database
```js
// find multiple entries
Project.findAll().then(function(projects) {
  // projects will be an array of all Project instances
})

// also possible:
Project.all().then(function(projects) {
  // projects will be an array of all Project instances
})

// search for specific attributes - hash usage
Project.findAll({ where: { name: 'A Project' } }).then(function(projects) {
  // projects will be an array of Project instances with the specified name
})

// search with string replacements
Project.findAll({ where: ["id > ?", 25] }).then(function(projects) {
  // projects will be an array of Projects having a greater id than 25
})

// search within a specific range
Project.findAll({ where: { id: [1,2,3] } }).then(function(projects) {
  // projects will be an array of Projects having the id 1, 2 or 3
  // this is actually doing an IN query
})

// or
Project.findAll({ where: "name = 'A Project'" }).then(function(projects) {
  // the difference between this and the usage of hashes (objects) is, that string usage
  // is not sql injection safe. so make sure you know what you are doing!
})

// since v1.7.0 we can now improve our where searches
Project.findAll({
  where: {
    id: {
      gt: 6,              // id > 6
      gte: 6,             // id >= 6
      lt: 10,             // id < 10
      lte: 10,            // id
      ne: 20,             // id != 20
      between: [6, 10],   // BETWEEN 6 AND 10
      nbetween: [11, 15], // NOT BETWEEN 11 AND 15
      in: [1, 2],         // IN [1, 2]
      like: '%hat',       // LIKE '%hat'
      nlike: '%hat'       // NOT LIKE '%hat'
      ilike: '%hat'       // ILIKE '%hat' (case insensitive)
      nilike: '%hat'      // NOT ILIKE '%hat'
      overlap: [1, 2]     // && [1, 2] (PG array overlap operator)
    }
  }
})
```

### Complex filtering / OR queries

Since `v1.7.0-rc3`, it is possible to do complex where queries with multiple levels of nested AND and OR conditions. In order to do that you can use `Sequelize.or` and `Sequelize.and` and pass an arbitrary amount of arguments to it. Every argument will get transformed into a proper SQL condition and gets joined with the either `AND` or `OR`.

```js
Project.find({
  where: Sequelize.and(
    { name: 'a project' },
    Sequelize.or(
      { id: [1,2,3] },
      { id: { lt: 10 } }
    )
  )
})
```

This code will generate the following query:

```sql
SELECT *
FROM `Projects`
WHERE (
  `Projects`.`name`='a project'
   AND (`Projects`.`id` IN (1,2,3) OR `Projects`.`id` < 10)
)
LIMIT 1
;
```

Notice, that instead of `Sequelize.and` you can also use a plain array which will be treated as `Sequelize.and` if it contains objects or hashes or other complex data types. Furthermore you can use `Sequelize.or` as value for the where clause.

### Manipulating the dataset with limit, offset, order and group

To get more relevant data, you can use limit, offset, order and grouping:

```js
// limit the results of the query
Project.findAll({ limit: 10 })

// step over the first 10 elements
Project.findAll({ offset: 10 })

// step over the first 10 elements, and take 2
Project.findAll({ offset: 10, limit: 2 })
```

The syntax for grouping and ordering are equal, so below it is only explained with a single example for group, and the rest for order. Everything you see below can also be done for group

```js
Project.findAll({order: 'title DESC'})
// yields ORDER BY title DESC

Project.findAll({group: 'name'})
// yields GROUP BY name
```

Notice how in the two examples above, the string provided is inserted verbatim into the query, i.e. column names are not escaped. When you provide a string to order / group, this will always be the case as per v 1.7.0. If you want to escape column names, you should provide an array of arguments, even though you only want to order / group by a single column

```js
something.find({
  order: [
    'name',
    // will return `name`
    'username DESC',
    // will return `username DESC` -- i.e. don't do it!
    ['username', 'DESC'],
    // will return `username` DESC
    sequelize.fn('max', sequelize.col('age')),
    // will return max(`age`)
    [sequelize.fn('max', sequelize.col('age')), 'DESC'],
    // will return max(`age`) DESC
    [sequelize.fn('otherfunction', sequelize.col('col1'), 12, 'lalala'), 'DESC'],
    // will return otherfunction(`col1`, 12, 'lalala') DESC
    [sequelize.fn('otherfunction', sequelize.fn('awesomefunction', sequelize.col('col'))), 'DESC']
    // will return otherfunction(awesomefunction(`col`)) DESC, This nesting is potentially infinite!
    [{ raw: 'otherfunction(awesomefunction(`col`))' }, 'DESC']
    // This won't be quoted, but direction will be added
  ]
})
```

To recap, the elements of the order / group array can be the following:

* String - will be quoted
* Array - first element will be qouted, second will be appended verbatim
* Object -
  * Raw will be added verbatim without quoting
  * Everything else is ignored, and if raw is not set, the query will fail
* Sequelize.fn and Sequelize.col returns functions and quoted cools

### Raw queries

Sometimes you might be expecting a massive dataset that you just want to display, without manipulation. For each row you select, Sequelize creates a_DAO_, with functions for update, delete, get associations etc. If you have thousands of rows, this might take some time. If you only need the raw data and don't want to update anything, you can do like this to get the raw data.

```js
// Are you expecting a masssive dataset from the DB, and don't want to spend the time building DAOs for each entry?
// You can pass an extra query option to get the raw data instead:
Project.findAll({ where: ... }, { raw: true })
```

### count - Count the occurences of elements in the database

There is also a method for counting database objects:

```js
Project.count().then(function(c) {
  console.log("There are " + c + " projects!")
})

Project.count({ where: ["id > ?", 25] }).then(function(c) {
  console.log("There are " + c + " projects with an id greater than 25.")
})
```

### max - Get the greatest value of a specific attribute within a specific table

And here is a method for getting the max value of an attribute:

```js
/*
  Let's assume 3 person objects with an attribute age.
  The first one is 10 years old,
  the second one is 5 years old,
  the third one is 40 years old.
*/
Project.max('age').then(function(max) {
  // this will return 40
})

Project.max('age', { where: { age: { lt: 20 } } }).then(function(max) {
  // will be 10
})
```

### min - Get the least value of a specific attribute within a specific table

And here is a method for getting the min value of an attribute:

```js
/*
  Let's assume 3 person objects with an attribute age.
  The first one is 10 years old,
  the second one is 5 years old,
  the third one is 40 years old.
*/
Project.min('age').then(function(min) {
  // this will return 5
})

Project.min('age', { where: { age: { gt: 5 } } }).then(function(min) {
  // will be 10
})
```

### sum - Sum the value of specific attributes

In order to calculate the sum over a specific column of a table, you can
use the `sum` method.

```js
/*
  Let's assume 3 person objects with an attribute age.
  The first one is 10 years old,
  the second one is 5 years old,
  the third one is 40 years old.
*/
Project.sum('age').then(function(sum) {
  // this will return 55
})

Project.sum('age', { where: { age: { gt: 5 } } }).then(function(sum) {
  // wil be 50
})
```

## Eager loading

When you are retrieving data from the database there is a fair chance that you also want to get their associations. This is possible since`v1.6.0`and is called eager loading. The basic idea behind that, is the use of the attribute`include`when you are calling`find`or`findAll`. Lets assume the following setup:

```js
var User = sequelize.define('User', { name: Sequelize.STRING })
  , Task = sequelize.define('Task', { name: Sequelize.STRING })
  , Tool = sequelize.define('Tool', { name: Sequelize.STRING })

Task.belongsTo(User)
User.hasMany(Task)
User.hasMany(Tool, { as: 'Instruments' })

sequelize.sync().done(function() {
  // this is where we continue ...
})
```

OK. So, first of all, let's load all tasks with their associated user.

```js
Task.findAll({ include: [ User ] }).then(function(tasks) {
  console.log(JSON.stringify(tasks))

  /*
    [{
      "name": "A Task",
      "id": 1,
      "createdAt": "2013-03-20T20:31:40.000Z",
      "updatedAt": "2013-03-20T20:31:40.000Z",
      "UserId": 1,
      "user": {
        "name": "John Doe",
        "id": 1,
        "createdAt": "2013-03-20T20:31:45.000Z",
        "updatedAt": "2013-03-20T20:31:45.000Z"
      }
    }]
  */
})
```

Notice that the accessor of the associated data is the name of the model in camelcase with lowercased first character. Also the accessor is singular as the association is one-to-something.

Next thing: Loading of data with many-to-something associations!

```js
User.findAll({ include: [ Task ] }).then(function(users) {
  console.log(JSON.stringify(users))

  /*
    [{
      "name": "John Doe",
      "id": 1,
      "createdAt": "2013-03-20T20:31:45.000Z",
      "updatedAt": "2013-03-20T20:31:45.000Z",
      "tasks": [{
        "name": "A Task",
        "id": 1,
        "createdAt": "2013-03-20T20:31:40.000Z",
        "updatedAt": "2013-03-20T20:31:40.000Z",
        "UserId": 1
      }]
    }]
  */
})
```

Notice that the accessor is plural. This is because the association is many-to-something.

If an association is aliased (using the`as`option), you_must_specify this alias when including the model. Notice how the user's`Tool`s are aliased as`Instruments`above. In order to get that right you have to specify the model you want to load, as well as the alias:

```js
User.findAll({ include: [{ model: Tool, as: 'Instruments' }] }).then(function(users) {
  console.log(JSON.stringify(users))

  /*
    [{
      "name": "John Doe",
      "id": 1,
      "createdAt": "2013-03-20T20:31:45.000Z",
      "updatedAt": "2013-03-20T20:31:45.000Z",
      "instruments": [{
        "name": "Toothpick",
        "id": 1,
        "createdAt": null,
        "updatedAt": null,
        "UserId": 1
      }]
    }]
  */
})
```

### Ordering Eager Loaded Associations

In the case of a one-to-many relationship.

```js
Company.findAll({ include: [ Division ], order: [ [ Division, 'name' ] ] });
Company.findAll({ include: [ Division ], order: [ [ Division, 'name', 'DESC' ] ] });
Company.findAll({
  include: [ { model: Division, as: 'Div' } ],
  order: [ [ { model: Division, as: 'Div' }, 'name' ] ]
});
Company.findAll({
  include: [ { model: Division, include: [ Department ] } ],
  order: [ [ Division, Department, 'name' ] ]
});
```

In the case of many-to-many joins, you are also able to sort by attributes in the through table.

```js
Company.findAll({
  include: [ { model: Division, include: [ Department ] } ],
  order: [ [ Division, DepartmentDivision, 'name' ] ]
});
```

### Nested eager loading
```js
User.findAll({
  include: [
    {model: Tool, as: 'Instruments', include: [
      {model: Teacher, include: [ /* etc */]}
    ]}
  ]
}).then(function(users) {
  console.log(JSON.stringify(users))

  /*
    [{
      "name": "John Doe",
      "id": 1,
      "createdAt": "2013-03-20T20:31:45.000Z",
      "updatedAt": "2013-03-20T20:31:45.000Z",
      "instruments": [{ // 1:M and N:M association
        "name": "Toothpick",
        "id": 1,
        "createdAt": null,
        "updatedAt": null,
        "UserId": 1,
        "Teacher": { // 1:1 association
          "name": "Jimi Hendrix"
        }
      }]
    }]
  */
})
```

**Final note:**If you include an object which is not associated, Sequelize will throw an error.

```js
Tool.findAll({ include: [ User ] }).then(function(tools) {
  console.log(JSON.stringify(tools))
})

// Error: User is not associated to Tool!
```

[0]: #configuration
[1]: https://github.com/epeli/underscore.string
[2]: #get_and_set_helper_funcs
[3]: https://github.com/chriso/validator.js
[4]: https://github.com/chriso/node-validator
[5]: /docs/latest/misc#asynchronicity
[6]: https://github.com/petkaantonov/bluebird/blob/master/API.md#spreadfunction-fulfilledhandler--function-rejectedhandler----promise

repository: MagicIndustries/sequelize

repo_name: MagicIndustries/sequelize


text:
# ivmJV

**ivmJV** is a tool to validate string as JSON object.
The tool will respect [RFC8259], but I have not thoroughly tested it to complain in full with the standard.

# Install
```yaml
  dependencies:
    ivmjv: any
```
Run `pub get`

# Example

To test a string if it can be a valid JSON object, import the library,
create an instance of `JsonValidator` class and pass the string to be tested as initial parameter.

```dart
void main() {
  JsonValidator iv = JsonValidator("{\"amount\": 100.00}");
  print('valid?: ${iv.validate()}');
}
```

repository: dasiyes/ivmjv

repo_name: dasiyes/ivmjv


text:
### [CVE-2019-6984](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-6984)
![](https://img.shields.io/static/v1?label=Product&message=n%2Fa&color=blue)
![](https://img.shields.io/static/v1?label=Version&message=n%2Fa&color=blue)
![](https://img.shields.io/static/v1?label=Vulnerability&message=n%2Fa&color=brighgreen)

### Description

An issue was discovered in Foxit 3D Plugin Beta before <IP_ADDRESS>07 for Foxit Reader and PhantomPDF. The application could encounter a Use-After-Free or Type Confusion and crash during handling of certain PDF files that embed specifically crafted 3D content, due to the use of a wild pointer.

### POC

#### Reference
No PoCs from references.

#### Github
- https://github.com/0xCyberY/CVE-T4PDF
- https://github.com/ARPSyndicate/cvemon

repository: trickest/cve

branch_name: refs/heads/main

gha_language: HTML

gha_license_id: MIT

repo_name: trickest/cve


text:
# docs_gm

[![Greenkeeper badge](https://badges.greenkeeper.io/jhm-ciberman/docs_gm.svg)](https://greenkeeper.io/)
[![npm](https://img.shields.io/npm/dt/docs_gm.svg)](https://www.npmjs.com/package/docs_gm)
[![npm](https://img.shields.io/npm/v/npm.svg)](https://www.npmjs.com/package/docs_gm)
[![Build Status](https://travis-ci.org/jhm-ciberman/docs_gm.svg?branch=master)](https://travis-ci.org/jhm-ciberman/docs_gm)
[![Coverage Status](https://coveralls.io/repos/github/jhm-ciberman/docs_gm/badge.svg?branch=master)](https://coveralls.io/github/jhm-ciberman/docs_gm?branch=master)
[![Maintainability](https://api.codeclimate.com/v1/badges/292b9c69320b1acfaf37/maintainability)](https://codeclimate.com/github/jhm-ciberman/docs_gm/maintainability)

> The fantastic documentation generator for GameMaker:Studio and GameMaker Studio 2

![docs_gm: The fantastic documentation generator for GM:S & GMS2](img/docs_gm_logo.png)

## ✅ Features

- Supports both GMS1 and GMS2 projects.
- It's Multiplatform! Windows, OSX and Linux supported.
- Easily customizable template engine.
- OnePage and Multipage documentations.
- Supports a lot of JSDoc tags!
- Markdown supported!
- Reports when some scripts are bad documented, or lack documentation.

## ☁ Installation

Install [Node JS from the official website](https://nodejs.org/).
Then open the windows console and install it with the following command:

```bash
npm install -g docs_gm
```

To view the HELP of docs_gm run:

```bash
docs_gm --help
```

You can also see the help for some specific command:

```bash
docs_gm generate --help
```

----------

## ❓ How to use it

### > First: Document your project

You will need to document your scripts following JSDoc syntax. You can learn more about in the [official JSDoc website](http://usejsdoc.org/)

For example:  In the script `my_script`

```js
/// my_script(coffee_type, cakes_number [, clean_after_work]);
/**
 * This script will do a lot of things. Like make
 * coffee, and bake a cake. It will return the
 * index of the generated breakfast.
 *
 * @param {string} coffee_type - The type of coffee
 * you want
 * @param {integer} cakes_number - The number of cakes
 * to bake.
 * @param {boolean} [clean_after_work] - Specify if the
 * table must be cleaned after the baking process.
 * The default is true.
 *
 * @returns {Breakfast} The index of the generated
 * breakfast.
 */

if (argument[0] === "latte") {
   // your code here...
   // blah blah blah
   // more code
}
return foo;
```

docs_gm supports both `/// triple slash comments` and `/** JSDoc single line and multiline comments */`

The following JSDoc tags are supported by gm_docs:

- [`@description`, `@desc`, and inline description (like the above example)](http://usejsdoc.org/tags-description.html)
- [`@param`, `@arg`, `@argument`](http://usejsdoc.org/tags-param.html)
- [`@returns`, `@return`](http://usejsdoc.org/tags-returns.html)
- [`@private`](http://usejsdoc.org/tags-private.html)
- [`@function`, `@func`, `@method`](http://usejsdoc.org/tags-function.html)
- [`@example`](http://usejsdoc.org/tags-example.html)
- More tags will be supported in the next updates

### > Second: Run gm_docs from the command line

Navigate to the directory you have your GameMaker project. For example, for GameMaker:

```bash
cd C:\Users\YOUR_USER\Documents\GameMaker\Projects\my-project-name
```

or for GameMaker:Studio 2 (windows)

```bash
cd C:\Users\YOUR_USER\Documents\GameMakerStudio2\my-project-name
```

To GENERATE the documentation for the current project run:

```bash
docs_gm generate
```

If you want to change the default (Ugly) configuration run the following command and follow the instructions on the screen to add the configuration file to your project.

```bash
docs_gm init
```

You must follow the instructions that appears on the console and then you can edit the configuration file with any text editor and re-run `docs_gm generate`.

You can also override some specific configuration using the arguments on the console. For example, to change the design to use:

```bash
docs_gm generate --design myDesignName
```

## Changing the template and design

Each **template** can have multiple **designs**.

`docs_gm` includes [one integrated default template](https://github.com/jhm-ciberman/docs_gm-basic) (called `docs_gm-basic`).
That template includes four possible designs:

- `onepage`: (The default design) Shows all the project scripts in one single HTML pages with a table of contents. It does not shows the folder structure. Ideal for smaller projects.
- `multipage`: Each script documentation is generated in a separate HTML file, and the index file contains a table of contents with links to each script page. It does not shows the project folder structure. Ideal for medium sizes projects.
- `modules-onepage`: Each script and each folder is generated in a separate HTML file. Each folder shows the folder children with the documentation of each script on the same page. It shows the folder structure. Ideal for big sized projects.
- `modules-multipage`: Each script and each folder is generated in a separate HTML file. Each folder shows the folder children with links to each one and to his parent folder. It shows the folder structure, but it requires more clicks to reach an specific script documentation. Ideal for huge sized projects.

For example, if you want to change the **design**, you can change the `design` value in your configuration file (See `docs_gm init`) to the design name you want to use. For example:

```json
"design": "multipage",
```

You can also change the name of the template to use (the template package must be installed globally). For example, if you have a template named `docs_gm-awesome-template`, you can write this in your configuration file:

```json
"template": "awesome-template",
```

Another alternative is to set the values using the console:

```bash
docs_gm generate --design multipage --template awesome-template
```

Check the help for the `generate` command with `docs_gm generate --help` to see all the possible values that can be overwritten in the console.

## Custom templates

You can create custom HTML templates and use them with docs_gm. Refer to [this page](./custom_templates.md) for how to create a custom template.

## Folder scoped documentation

If you want to add documentation for one folder containing multiple scripts, you can create a GameMaker script called: `FOLDER_anyname` or `MODULE_anyname` inside your folder and add a simple JSDoc comment inside that script with the documentation for your module. You can use [markdown](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet).

For example:

```text
+ scripts [root folder]
  + inventory_system [folder]
    - FOLDER_inventory_system [script]
    - inventory_add_item [script]
    - inventory_get_item [script]
    - inventory_draw [script]
```

Inside FOLDER_inventory_system script you can write something like this:

```js
/**
 * Inventory System
 * ================
 *
 * > By Javier "Ciberman" Mora
 *
 * You can use this functions to create your inventory
 * and you need to... bla bla bla...
 * More documentation **with markup** here.
 *
 * - You can create bullets
 * - with items
 *
 * And also add [links](http://google.com).
 */
```

Then you can use any template with a design that supports modules. (For example the `docs_gm-basic` Template has `modules-onepage` and `modules-multipage` designs.)

> Note: you can create multiple subfolders and document each one with one `MODULE_` or `FOLDER_` script inside each subfolder.

## Contribute

I would love to see people interested in contributing to docs_gm. If you have some idea, or bug, you can send a Issue in the github page. Also, you can check the [contribute document](CONTRIBUTE.md)

## Contributors

- Javier "Ciberman" Mora ([@jhm-ciberman](https://github.com/jhm-ciberman/)) Maintainer
- Peter Hagen ([@phgn0](https://github.com/phgn0))


text:
# EasyTo: TODO APP 📝
 Task management application developed with clean architecture, MVVM, ROOM, Firebase and SOLID principles

## Built With 🛠

- Kotlin
- Clean architecture
- MVVM
- Dagger Hilt
- Firebase (Firestore, Storage, Auth)
- Room
- Live Data
- Coroutines Flow
- ViewBinding
- Fragments/Activity's
- SOLID

## Architecture 📐

![Test Image 4](screenshots/architecture_app.png)

## Screenshots 📱

| Login Screen | Home |  Task details |
|:-:|:-:|:-:|
| ![Fist](screenshots/easyto_login_sc_white.png?raw=true) | ![3](screenshots/easyto_home_sc_white.png?raw=true) | ![3](screenshots/easyto_task_sc_white.png?raw=true) |
| Login Screen Dark | Home Dark |  Details Dark |
| ![4](screenshots/easyto_login_sc_black.png?raw=true) | ![5](screenshots/easyto_home_sc_black.png?raw=true) | ![6](screenshots/easyto_task_sc_black.png?raw=true) |

## Package Structure 📦

```bash

com.jcisneros.easyto # Root Package
├── di                  # Hilt DI Modules
├── data                # For data handling.
│   ├── datasource      # Datasource for app
|   │   ├── firebase    # Firebase data sources
|   │   │   ├── auth
|   │   │   ├── taskdetail
|   │   │   ├── tasks
|   │   ├── local       # Local Persistence Database.
|   │   │   ├── room    # Room (SQLite) database
|   │   │   │    ├── dao
|   │   │   │    ├── database
|   │   │   │    ├── entities
|   │   │   ├── auth
|   │   │   ├── taskdetail
|   │   │   ├── tasks
|   │   ├── interfaces  # Interfaces for datasources implements
│   ├── model           # Data model for app
|
├── domain              # domain layer (for repository handling)
│   ├── repository      # Used to handle all data operations
|   │   ├── auth
|   │   ├── taskdetail
|   │   ├── tasks
|
├── presentation        # Presentation layer (Activity/Fragment and VM)
│   ├── base            # To have classes with UI logic
│   ├── login           # Activity/Fragment, VM's
│   ├── taskdetail      # Activity/Fragment, VM's
│   ├── tasks           # Activity/Fragment, VM's and adapter
|
├── utils               # All utils class

```

## License 🔖
```
                               Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   Copyright 2021 Juan Cisneros

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.

```


text:
# Louisiana Groups

👥 Public list of Louisiana tech and creative groups.

## Table of Contents

* [Louisiana Groups](#louisiana-groups)
	* [Roadmap](#roadmap)
	* [Development](#development)
	* [Tech Used](#tech-used)
	* [Contributors](#contributors)
	* [Notes](#notes)
	* [Contributing](#contributing)
	* [License](#license)

## Roadmap

* [x] Upgrade to FontAwesome5 + brands
* [x] Add website and social links to cards
* [x] Add isotope for toggle and search filtering [Isotope Codepen](https://codepen.io/desandro/pen/wfaGu)
* [x] Add "next meetup" to group cards
* [x] Sort groups by last meetup, making the more active groups float to the top
* [x] Add submit forms for adding new groups and group events

## Development

When you’re ready to rock, clone the project:

```shell
git clone https://github.com/LouisianaGroups/louisiana-groups.git
```

You’re all set! That was it! To run the project, just open the index.html:

Happy hacking!

## Tech Used

| Needed | Used |
| ------ | ------ |
| CSS Grid System, etc. | [Bootstrap 4](http://getbootstrap.com)
| JavaScript DOM manipulation | [jQuery](http://jquery.com)
| Font Icons | [Font Awesome 5](https://fontawesome.com) + [brands](https://fontawesome.com/icons?d=brands)
| Database | [Google Sheets](https://google.com/sheets)
| Google Sheets querying | [Sheetrock.js](https://chriszarate.github.io/sheetrock)
| Templating | [KnockoutJS](https://knockoutjs.com)
| UI Filtering | [Isotope](https://isotope.metafizzy.co)
| Select element styling (for location select) | [Stylish Select](https://github.com/adamculpepper/stylish-select)
| Select element styling (for modal select) | [Select2](https://select2.org)
| Date calculations | [Moment.js](https://momentjs.com)
| Form to Google Sheets API | [Google Scripts](https://script.google.com)
| Form Validation | [Parsley](https://parsleyjs.org)
| Datetime Picker | [Bootstrap Datetimepicker](https://eonasdan.github.io/bootstrap-datetimepicker)
| Analytics Tracking | [Google Analytics](https://google.com/analytics)
| Content Delivery Network | [KeyCDN](https://www.keycdn.com/?a=62386)

## Contributors

* [Adam Culpepper](https://github.com/adamculpepper)
* [N. G. Scheurich](https://nick.scheurich.me)
* [James Alt](https://github.com/james-alt)

## Notes

This is a volunteer project, so we're not putting high priority on old browser compatibility support. Use a real browser. :smiley:

## Contributing

Want to contribute? Awesome! Contributions are always welcome — just be sure to read and follow the [code of conduct](https://github.com/babel/babel/blob/master/CODE_OF_CONDUCT.md).

## License

This project is released under the [MIT license](https://github.com/LouisianaGroups/louisiana-groups/blob/master/LICENSE).

repository: LouisianaGroups/louisiana-groups

gha_language: JavaScript

repo_name: LouisianaGroups/louisiana-groups


text:
## RUST

We make use of async/await and therefor we *need* a compiler that supports that. We currently
use the nightly compiler. Nightly is required in all of the provided build possibilities listed below

Build options
==================
- [Building with Nix (recommended)](#Building-the-sources-with-nixpkg)
- [Build inside docker](#Build-inside-docker)
- [Building the hard way](#Build-it-the-hard-way)

## Building the sources with nixpkg

As the underlaying distribution you can use nixos or any other linux
distribution if you install a nix package manager on top of it.
Example of nixos system configuration `/etc/nixos/configuration.nix`
suitable for a dev box:

```nix
{ config, pkgs, ... }:

{
  imports =
    [ # Include the results of the hardware scan.
      ./hardware-configuration.nix
    ];
  boot.loader.grub.enable = true;
  boot.loader.grub.version = 2;
  boot.loader.grub.device = "/dev/sda"; # or whatever is appropriate
  boot.kernelModules = ["nbd" "xfs" "nvme_tcp"];
  boot.kernelParams = ["hugepages=512" "hugepagesz=2MB"];
  services.openssh.enable = true;
  virtualisation.docker.enable = true;
  users.users.your_username = {
    isNormalUser = true;
    extraGroups = [ "wheel" "docker" ];
  };
  system.stateVersion = "19.03";
  security.sudo.enable = true;
  security.sudo.wheelNeedsPassword = false;
}
```

Installation of a [nix package manager](https://nixos.org/nix/download.html) on
other distros:

```bash
curl -L https://nixos.org/nix/install | sh
```

We have provided a `shell.nix` file that can be used to build and compile
MayaStor from source without impacting your system.
Follow the short instruction and you should be all set!

```bash
cd MayaStor
nix-shell
git submodule update --init
cargo build --all
```

Binaries will be installed in `$(CURDIR)/target/release` after running the build you can use
`$(CURDIR)/target/release/mayastor-client` to create a Nexus.

## Build inside docker

This is most close to the environment used for building and testing of
MayaStor in our github CI/CD pipeline. But could be used for other purposes
as well. The following command starts a container with build environment
for MayaStor. The sources are mounted from the host at /code/MayaStor.
That is optional. You can clone the sources from github instead.

```bash
docker run -it --privileged -v /dev:/dev:rw -v /dev/shm:/dev/shm:rw \
    -v /dev/hugepages:/dev/hugepages:rw --network host \
    -v /code/MayaStor:/MayaStor mayadata/ms-buildenv:latest /bin/sh
```

Docker image is essentially just a nixos image with a couple of
utilities and pre-built mayastor dependencies. You can just
enter the nix shell and build the mayastor.

```bash
cd MayaStor
nix-shell
git submodule update --init
cargo build --all
```

After that you should be able to start MayaStor:

```bash
$ ./target/debug/mayastor
main.rs:  28:: *NOTICE*: free_pages: 658 nr_pages: 1024
Starting SPDK v19.07 / DPDK 19.05.0 initialization...
[ DPDK EAL parameters: MayaStor --no-shconf -c 0x1 --log-level=lib.eal:6 --log-level=lib.cryptodev:5 --log-level=user1:6 --base-virtaddr=0x200000000000 --match-allocations --file-prefix=spdk_pid57086 ]
app.c: 627:spdk_app_start: *NOTICE*: Total cores available: 1
reactor.c: 251:_spdk_reactor_run: *NOTICE*: Reactor started on core 0
nexus_module.rs: 105:: *NOTICE*: Initializing Nexus CAS Module
cryptodev_aesni_mb_create() line 1304: IPSec Multi-buffer library version used: 0.52.0

executor.rs:  94:: *INFO*: Started future executor on thread ThreadId(1)
iscsi_target.rs:  85:: *INFO*: Created default iscsi portal group
iscsi_target.rs: 100:: *INFO*: Created default iscsi initiator group
nvmf_target.rs: 294:: *NOTICE*: Created nvmf target at <IP_ADDRESS>:4401
tcp.c: 535:spdk_nvmf_tcp_create: *NOTICE*: *** TCP Transport Init ***
nvmf_target.rs: 344:: *NOTICE*: Added tcp nvmf transport <IP_ADDRESS>:4401
tcp.c: 730:spdk_nvmf_tcp_listen: *NOTICE*: *** NVMe/TCP Target Listening on <IP_ADDRESS> port 4401 ***
nvmf_target.rs: 364:: *NOTICE*: nvmf target listens on <IP_ADDRESS>:4401
nvmf_target.rs: 415:: *NOTICE*: nvmf target <IP_ADDRESS>:4401 accepts new connections
main.rs:  31:: *NOTICE*: MayaStor started (fcaf10b-modified)...
```

Feel free to change the [DockerFile](../Dockerfile) to your convenience.

### Justifications for the volume mounts:

- `/dev` is needed to get access to any raw device you might want to consume as local storage and huge pages
- `/dev/shm` is needed as for a circular buffer that can trace any IO operations as they happen
- `--network host` is needed because we dont not use virtual networks (to reduce latency impact)
- `/code/MayaStor` the host path to your checked out source code

## Running tests within the container

If you wish to run some of our higher-level test cases (like for example CSI), you need to make sure you have the
proper kernel modules loaded (nbd, xfs and nvme_tcp) as well as allocate at least some 2MB hugepages.

```bash
modprobe {nbd,xfs,nvme_tcp}
echo 512 | sudo tee  /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages
```

Then, for example:

```bash
root@gilakubuntu:/MayaStor/test/grpc# ./node_modules/mocha/bin/mocha test_csi.js
  csi
    identity
      ✓ probe
      ✓ get plugin info
      ✓ get plugin capabilities
    node
      ✓ get info
      ✓ get capabilities
    stage and unstage xfs volume
      ✓ should be able to stage volume (69ms)
      ✓ get volume stats (62ms)
      ✓ staging the same volume again should return ok (idempotent)
      ✓ staging a volume with a non existing bdev should fail with Internal Error (57ms)
      ✓ staging a volume with the same staging path but with a different bdev should fail
      ✓ should fail to stage a volume with the bdev using a different target path
      ✓ should not unstage a volume with an unknown volumeid and return NOTFOUND error (51ms)
      ✓ should fail to stage a volume with a missing volume ID
      ✓ should fail to stage a volume with a missing stage target path
      ✓ should fail to stage a volume with a missing access type
      ✓ should fail to stage a volume with a missing accces mode
      ✓ should fail to stage a volume with missing volume_capability section
      ✓ should be able to unstage volume
    stage and unstage ext4 volume
      ✓ should be able to stage volume (59ms)
      ✓ should be able to unstage volume (38ms)
    stage misc
      ✓ should fail to stage unsupported fs
      ✓ should clean up nbd dev upon mount failure (47ms)
    publish and unpublish
      MULTI_NODE_READER_ONLY staged volume
        ✓ should publish a volume in ro mode and test it is idempotent op
        ✓ should fail when re-publishing with a different staging path
        ✓ should fail with a missing target path
        ✓ should fail to publish the volume as rw
        ✓ should be able to unpublish ro volume (56ms)
        ✓ should be able to unpublish rw volume
      MULTI_NODE_SINGLE_WRITER staged volume
        ✓ should publish ro volume
        ✓ should publish rw volume (58ms)
        ✓ should be able to unpublish ro volume
        ✓ should be able to unpublish rw volume

```

If you wish to run the MayaStor data path tests, make sure you specify `test-threads=1`

```bash
cargo test  -- --test-threads=1
```

## Build it the hard way

When you really want to build everything manually, the biggest hurdle to overcome is to install the SPDK/DPDK. As these
are not packaged (or not recent) by most distro's its a manual step. We have provided scripts to make this as easy as
possible but they only work for Ubuntu and Fedora.

The basic steps are:

```
git submodule update --init --recursive
sudo ./spdk-sys/spdk/scripts/pkgdep
./spdk-sys/build.sh --enable-debug --without-isal --with-iscsi-initiator --with-rdma \
             --with-internal-vhost-lib --disable-tests \
             --with-crypto
```
At this point you will have a .so file in `spdk-sys/build` you can leave it there and set the run path flag for rustc to find it:

```
export RUSTFLAGS="-C link-args=-Wl,-rpath=$(pwd)/spdk-sys/build"
```

Or, you can copy over the .so to `/usr/local/lib` or something similar.

One this is done, you should be able to run `cargo build --all`

## Building docker images

Use NIX to build the images. Note that the images are based on NIX packages
that are built as part of building the image. The tag of the image will be
short commit hash of the top-most commit or a tag name of the commit if
present. Example of building a moac package:

```bash
nix-build -A images.moac-image
```

At the end of the build is printed path to docker image tar archive. Load the
image into Docker (don't use _import_ command) and run bash to poke around:

```bash
docker load -i /nix/store/hash-docker-image-moac.tar.gz
docker run --rm -it image-hash /bin/bash
```

Mayastor and csi plugin images can have multiple flavours. Production image
name does not contain the flavour name (i.e. `mayastor-image`). Debug image
contains the `dev` in its name (i.e. `mayastor-dev-image`). Mayastor package
has additional flavour called `adhoc` (`mayastor-adhoc-image`), that is handy
for testing because it is not based on mayastor package but rather on whatever
binaries are present in `target/debug` directory.

## Some background information

MayaStor makes use of subsystems that are not yet part of major distributions, for example:

     - nvme-tcp initiator (Linux 5.x and newer)
     - Recent DPDK version (i.e 19.x)

Fortunately, this is something that will be solved over time automatically. In the meantime, we have
tried to make it as simple as possible by providing several options for you.

Mayastor, in all cases, **requires the nightly rust compiler with async support**.
You don't need to have a 5.x kernel unless you want to use NVMF.

If you already have rust installed but not nightly, use rustup to install it before continuing.

### spdk-sys

The crate that provides the glue between SPDK and Mayastor is hosted in this [repo](https://github.com/openebs/spdk-sys)
feel free to go through it and determine if you want to install libspdk using those instructions or directly from
[here](https://github.com/openebs/spdk). If you chose either of these methods, make sure you install such that
during linking, it can be found.

repository: teamrebuild/Mayastor

gha_language: Rust

repo_name: teamrebuild/Mayastor


text:
# StudyBuddy Code Colab
StudyBuddy Python code collaboration repo.

### Buckle Up the fun is about to begin!!!

 ![picture alt](https://i.pinimg.com/originals/48/46/27/484627aacec4fc7fbdee8f2c31967ee4.gif "Title is optional")

### Purpose
Purpose of this repo is for the participants to share their code in an online repo for a more realistic software development experience.

### Process
* Commit your trial code in a folder with your name.
* Include a readme.md file or comments to explain your code.
* Edit/update your code online or from your local repo with update comments.
* Share your code link in slack - if slackbot does not already post your update in slack channel #github-updates

### StudyBuddy documents posted for participants
#### Python install presentations
* [Python installation VS Code and Online Editor](https://github.com/StudyBuddy2020/studybuddy/blob/master/Python%20Installation-With%20VS%20CODE%20and%20ONLINE%20EDITOR.pdf)
* [Python installation with Anaconda and Jupyter notebook](https://github.com/StudyBuddy2020/studybuddy/blob/master/Python-Installation-With%20ANACONDA%20AND%20JUPYTER%20NOTEBOOK.pdf)

#### Python install videos
* [Session1 - Python Basics](https://github.com/StudyBuddy2020/studybuddy/blob/master/SESSION%201%20-%20Python_Basics.mp4)
* [Session2 - Using Jupyter Notebook](https://github.com/StudyBuddy2020/studybuddy/blob/master/SESSION%202%20-%20Using_JupyterNtbk.mp4)

### Mardown Cheatsheet
https://github.com/tchapi/markdown-cheatsheet/blob/master/README.md

license: Unlicense


text:
---
comments: true
date: 2011-04-18 11:57:00+00:00
layout: post
title: Ha Long Bay
wordpress_id: 802
image: https://c3.staticflickr.com/2/1640/26647295986_1a33dc3ab7_q.jpg
locations:
  - Vietnam
  - Ha-Long-Bay
redirect_from:
  - /vietnam/ha-long-bay/vietnam-2011/ha-long-bay/
---

The next morning we had a fairly early start. We had to sort out an overnight bag for staying on a
boat in the bay, have breakfast and checkout by 7am. A tall order on most days, but especially
considering the amount of sleep we had all had in the last 2 days. However, by 07:05 we were getting
on the bus for another seemingly long journey south to Ha Long Bay. Hai spent about 45 minutes
giving us an endless stream of information about Hanoi and Ha Long Bay, what the plan was for the
next 24 hours and what we should expect. Unfortunately, by that time, he had lost half of his
audience to sleep so he gave in. We stopped at an interesting lacquer ware place on route but it was
only a loo stop so we weren’t there long. We arrived at the boat station at about 12 and jumped on a
transport boat to reach our accommodation for the next night.

{% flickr_image<PHONE_NUMBER>0 alignright %}

It was a lovely private boat for our group with twin and double sleeping rooms for everyone and a
sunbathing deck up top too. We checked into our rooms while lunch was prepared and then met up for a
selection of Ha Long Bay specialities for lunch. A much more seafood based meal this time, which
suited us, but not everyone likes seafood as much as we do. Unfortunately the spectacular views we
had been anticipated were nicely hidden behind the mists of the bay, but this gave a mystical look
to what we could see.

We cruised through the mist for a while before pulling into a small cove with a boat house and cave
behind. This was to be our first stop of the boat trip. The caves were just that, caves, but the
views out over the bay were stunning and absolutely worth the effort of walking up the
hillside/steps. After a quick look around the caves we jumped back on the boat for a trip to a pearl
farm.

{% flickr_photoset<PHONE_NUMBER>9889356 %}

The mist was clearing gradually as we approached the pearl farm so we were able to see more and more
of the bay. It was everything we had expected it to be apart from the blue skies, or lack thereof.
On arrival at the pearl farm, we were given double kayaks to explore the bay ourselves. This was
brilliant. Once we got used to being in the same kayak we were sorted and paddled around the whole
area for ages before heading back to the boat for a swim, well, I swam and Rosie watched. The water
was a bit murky, but quite pleasant to swim in, although I definitely felt the need for a shower
once I was back on board!

{% flickr_image<PHONE_NUMBER>2 aligncentre %}

As the dark began to settle over the bay, we had our evening meal and cruised into the only spot in
the area where we were allowed to drop anchor for the night, so we were soon surrounded by boats
like ours. Quite a comforting feeling really. After a few hours chatting and getting to know the
other people on the trip, we all turned in.

{% flickr_photoset<PHONE_NUMBER>9889336 %}

branch_name: refs/heads/pages

gha_language: Ruby


text:
fluentatious
=========================

## Motivation
Most of the C# I write is rather LINQ heavy. Readability / maintainability benefits aside, LINQ is a pleasure to use
and I find myself missing its functional and fluent nature whenever I'm writing non-LINQ code in C#. And I find it
especially jarring when I'm force to depart from functional coding and intersperse bits of imperative code. So here
are some of the fluent extensions / constructs which I've written in the past couple of years.

## What Fluentatious is:
A library of object extensions and constructs which aim to make it easier to write fluent and functional C#, even when
you're not working with LINQ. It aims to help you:
* Achieve fluency - to have nice code which flows from left to right like a pipeline in point-free style. No visual
jumping around necessary.
* Have fewer unnecessary local variables
* Mutate variables less often

## What Fluentatious isn't:
* An attempt to turn C# into a functional language by emulating functional constructs such as option types,
monads etc.
* A framework to aid in writing fluent interfaces of your own.

## Overview
All of the features below have usage examples and tests present in the code. Most are implemented as extensions methods
on Object, aside from Pattern.

---
### If / Unless / IfElse (object extension)

There are many things I don't like about the below piece of code. I don't like that my nice functional LINQ expression has
been cleaved in two by some imperative logic. And I don't like that I have to declare an unnecessary foos variable and
mutate it at various points.

    // Without If
    var foos = input
        .Where(str => str.StartsWith("a"))
        .Select(str => new Foo(str));

    if (sortingCriterion == SortingCriteria.Alphabetical)
        foos = foos.OrderBy(f => f.Bar);
    else if (sortingCriterion == SortingCriteria.LengthBased)
        foos = foos.OrderBy(f => f.Length);

    if (sortingDirection == SortingDirection.Descending)
        foos = foos.Reverse();

    return foos
        .Skip(1)
        .Take(5)
        .ToList();

Now, if only LINQ offered some sort of If expression... well, I initially implemented an IEnumerable extension called
'If', but later generalised it as an object extension. See the result below:

    return input
        .Where(str => str.StartsWith("a"))
        .Select(str => new Foo(str))
        .If(sortingCriterion == SortingCriteria.Alphabetical, foos => foos.OrderBy(f => f.Bar))
        .If(sortingCriterion == SortingCriteria.LengthBased, foos => foos.OrderBy(f => f.Length))
        .If(() => sortingDirection == SortingDirection.Descending, Enumerable.Reverse)
        .Skip(1)
        .Take(5)
        .ToList();

Note that If can take either a bool or a predicate (i.e. Func`<bool>`). Also, 'Unless' is provided as a convenience
method which operates identically to If, except that the condition/predicate is inverted.

Note that the first two Ifs following the Select could be replace by:
    // ...
        .IfElse(sortingCriterion == SortingCriteria.Alphabetical,
            foos => foos.OrderBy(f => f.Bar),
            foos => foos.OrderBy(f => f.Length))

---
### Pipe (object extension)

Pipe is pretty simple really... you can interpret it as 'take my input, pipe it into this function, return the result.
It's very easy to follow the flow of data and function calls. Pipe is intended to be used in a functional manner; i.e.
the specified transform functions should not mutate their input.

See the example below and observe that the non-pipe version isn't very point-free.  We coould could make it more readable by assigning intermediate
results to local variables, but that's something we're also trying to avoid. Or in the name of minimalism and
readability, we could use Pipe!

    // Without Pipe
    var blah = Compute(SomeMethod(SomeMethod("dhdhdh", Foo(Bar("horatio"))), "catatatat"));

    // Using Pipe
    var blah = "horatio"
        .Pipe(Bar)
        .Pipe(Foo)
        .Pipe(str => SomeMethod("dhdhdh", str))
        .Pipe(str => SomeMethod(str, "catatatat"))
        .Pipe(Compute)

    // Using Pipe in another way (you can combine Pipes as you see fit)
     var blah = "horatio".Pipe(Bar, Foo, str => SomeMethod("dhdhdh", str), str => SomeMethod(str, "catatatat"), Compute)

---
### Do (object extensions)
Do is inspired by the Underscore JS Tap function, of which Ruby also has an equivalent. It's actually quite
similar to Pipe with one important difference. Instead of piping the input into a Func and returning the result,
it performs any number of Actions on it in the order specified, and then returns the original object.

Do is intended to be fluent, but not necessarily functional. It's implied that any of the Actions can mutate
the input, although this isn't necessarily the case. Case in point... imagine you have this code and you want to
print the result of Sum for debugging purposes.

    // Original
    var length = new[] { "go", "tuk", "hodor" }
        .Select(i => i + i)
        .Sum(str => str.Length)
        .Pipe(i => Math.Max(i, 7);

Without Do, you'd split it like so:

    // Without Do
    var length = new[] { "go", "tuk", "hodor" }
        .Select(i => i + i)
        .Sum(str => str.Length);

    Console.WriteLine(length);

    return length.Pipe(i => Math.Max(i, 7);

Annoying. For the price of copious of keystrokes, you've managed to cleave your nice method chain into three and
introduce an unnecessary local var. All just to print the value of a variable. And then you have to clean up afterwards.
However, if you have a construct like Do / Tap, you can jump in an intercept the method chain to cleanly inject your
logging. Using Do:

    // With Do
    return new[] { "go", "tuk", "hodor" }
        .Select(i => i + i)
        .Sum(str => str.Length)
        .Do(Console.WriteLine)
        .Pipe(i => Math.Max(i, 7));

---
### NullSafe (object extension)

Performing tedious null checking is annoying, so I defined an object extension called NullSafe which I use
as below. It's a pretty simple example of continuation-style passing really. If the input to NullSafe isn't null,
its expression will be evaluated to produce something new... otherwise the entire expression will return null.
Basically, we're executing a series of expressions until a failure occurs at any point. It makes the code considerably
cleaner and allows us to achieve a nice fluent flow in point-free fashion.

    // Without NullSafe
    var value = input != null && input.Broccoli != null && input.Broccoli.Carrot != null
        ? (input.Broccoli.Carrot.Value + "asdfasdf")
        : null;

    // With NullSafe
    var value = input.NullSafe(i => i.Broccoli).NullSafe(b => b.Carrot).NullSafe(c => c.Value).NullSafe(v => v + "asdfasdf").Do(Console.WriteLine);

    // Alternatively
    var value = input.NullSafe(i => i.Broccoli, b => b.Carrot, c => c.Value, v => v + "asdfasdf").Do(Console.WriteLine);

Microsoft is actually planning to release a new language feature in C# 6 to address this very issue. You'll be able
to use it as per below. People refer to it as monadic null checking, because it's similar in behaviour to the
monadic bind operation in functional languages like Haskell. It's also similar to the way promises work in jQuery -
promises (can) allow you to string together synchronous/asynchronous actions which execute as normal until failure
occurs.

    // Future C# syntax
    var value = input?.Broccoli?.Carrot?.Value.NullSafe(v => v + "asdfasdf").Do(Console.WriteLine);

---
### CastTo / As (object extensions)
CastTo and As are pretty self-explanatory. They're simply method equivalents of intrinsic C# operators

    // Without CastTo / As
    var result1 = Foo(Foo((string) Foo((string) Foo("horatio"))) as string);
    var result2 = ((string) ("horatio".Pipe(Foo))).Substring(1).ToLowerInvariant().Trim();

    // With CastTo / As / Pipe

    var result1 = Foo("horatio").CastTo`<string>`().Pipe(Foo).CastTo`<string>`().Pipe(Foo).As`<string>`().Pipe(Foo);
    var result2 = "horatio".Pipe(Foo).CastTo`<string>`().Substring(1).ToLowerInvariant().Trim();

---
### Patterns (WARNING! Experimental toy which leads to hilariously unreadable code)
A Pattern (as in pattern matching) is essentially a fluent substitute for a series of if/then statements or a switch
statement, whose branches all conditionally assign different values to a local var. It is essentially a series
of ordered cases, where each case is composed of:
    # A condition or a predicate which is to be run against the subject of the pattern
    # An associated result or a bunch of associated subcases.

Patterns support:

* Two syntaxes for specifying predicates and associating them with results:
    * Case(condition, result)
    * Case(condition).Then(result)
* Default cases
* Subcases using three different syntaxes, which can be mixed:
    * Normal syntax:    Case / Default / Break (break is required to eliminate ambiguity)
    * Explicit syntax:  Case / Default / SubCase / SubDefault / SubSubCase / SubSubDefault
    * Lambda syntax:    As a supplement to the above two, subcases can by passing in a subcases lambda.
* A means of storing a parameterised predicate so that you need only pass in the thing which changes.
    Useful when you have a bunch of repetitive Case predicates which are practically identical aside from a
    changing input.

Example without patterns:

    // Without patterns
    string picture = null;

    if (d.Contains("Dogs"))
    {
        picture = "dogs.png";
    }
    else if (d.Contains("Cats"))
    {
        picture = "cats.png";
    }
    else if (d.Contains("Fish"))
    {
        if (d.Contains("Gourami"))
            picture = "gourami.png";
        else if (d.Contains("Tetra"))
            picture = "tetra.png";
    }
    else
    {
        picture = "fallback.png";
    }

    return Foo(picture).Length;

Example which realises the above as a mapping from bool conditions to string results:

    // Without patterns #2
    return new Dictionary`<Func<string, bool>, string>`
    {
        { str => str.Contains("Dogs"), "dogs.png" },
        { str => str.Contains("Cats"), "cats.png" },
        { str => str.Contains("Fish") && d.Contains("Gourami"), "gourami.png" },
        { str => str.Contains("Fish") && d.Contains("Tetra"), "tetra.png" },
        { str => !str.Contains("Fish") && d.Contains("Tetra"), "tetra.png" },
        { str => !str.Contains("Fish"), "fallback.png" }
    }
        .FirstOrDefault(kvPair => kvPair.Key(d))
        .Value
        .Pipe(Foo)
        .Length;

Example which uses Pattern:

    // With patterns
    return Pattern`<string, string>`
        .Match(s)
            .Case(s.Contains("Dogs"), "dogs.png")
            .Case(s.Contains("Cats"), "cats.png")
            .Case(s.Contains("Fish"))
                .Case(s.Contains("Gourami"), "gourami.png")
                .Case(s.Contains("Tetra"), "tetra.png")
                .Break()
            .Default("fallback.png")
        .ResolveFirst()
        .Pipe(Foo)
        .Length;

Super extreme example which shows off the capabilities of patterns:

    return Pattern`<string, string>`
        .Match(input)
        // Normal subcase case syntax using Case/Default/Break
        .Case(input.Contains("fish"))
            .Case(input.Contains("tetra"))
                .Case(input.Contains("neon"), "neon-tetra.png")
                .Case(input.Contains("blind cave"), "blind-cave-tetra.png")
                // Results can also be specified using Case/Then syntax
                .Case(input.Contains("glowlight")).Then("glowlight-tetra.png")
                .Case(input.Contains("colombian"), "colombian-tetra.png")
                // Default case
                .Default("unidentified-swimming-tetra.png")
                .Break()
            // Subcases can also be specified via a lambda
            .Case(input.Contains("gourami"), p => p
                .Case(input.Contains("dwarf"), "dwarf-gourami.png")
                .Case(input.Contains("pearl"), "pearl-gourami.png")
            )
            .Break()
        // I'm sick of repeating 'input.Contains()' everywhere! So let's store a predicate so that we need only specify the keywords
        .WithPredicate(substring => input.Contains((string)substring))
        // Explicit subcase syntax
        .Case("cat")
            .SubCase("manx").Then("manx.png")
            .SubCase("siamese")
                .SubSubCase("lynx", "lynx.png")
                // Explicit subcase methods also support Case/Then syntax
                .SubSubCase("lilac").Then("lilac.png")
                .SubSubDefault("generic-siamese-cat.png")
            // Lambda syntax for subcases can also supplemenent explicit subcases
            .SubCase("bengal", p => p
                .Case("angry", "angry-bengal-cat.png")
                .Case("happy", "happy-bengal-cat.png")
            )
        .Case("dog", "dog.png")
        .Case("bear")
            .SubCase("brown")
                .SubSubCase("irate", p => p
                    .Case("fast", "fast-irate-brown-bear.png")
                    .Case("deadly", "deadly-irate-brown-bear.png")
                    .Default("generic-irate-brown-bear.png")
                )
                .SubSubCase("mild", "mild-brown-bear.png")
                .SubSubCase("calm", p => p
                    .Case("fast")
                        .SubCase("smart")
                            .SubSubCase("alpha", "alpha-smart-fast-calm-brown-bear.png")
                            .SubSubCase("beta", p2 => p2
                                .Case("super", "super-beta-smart-fast-calm-brown-bear.png")
                                .Case("duper", "duper-beta-smart-fast-calm-brown-bear.png"))
                            .SubSubDefault("generic-smart-fast-calm-brown-bear.png")
                        .SubCase("dumb", "dumb-fast-calm-brown-bear.png")
                        .SubDefault("generic-fast-calm-brown-bear.png")
                    .Case("deadly", "deadly-calm-brown-bear.png")
                    .Default("generic-calm-brown-bear.png"))
            .SubCase("black", "black-bear.png")
            .SubDefault("generic-bear.png")
        .ResolveFirst();

repository: Seltzer/fluentatious

repo_name: Seltzer/fluentatious


text:
---
layout: page
title: Web Testing and Scraping with Modern Python Tools
permalink: /web-testing/
---

This course is a one day course on learning the basics of functional web testing and web
scraping with industry standard courses. It can be taught on-site or premises. The course
contents can be tailored to your specific needs and requirements.

This course assumes a basic knowledge of Python scripting but it doesn't require full knowledge of
the lanugage or object oriented programmers. It's suitable for beginner programmers or
those migrating from a testing role to a web programming role. It's often delivered as a
follow-on course form [Practical Python](/practical-python) or
[Beginning Python](/beginning-python).

I've been building web applications commercially for four years, and working with web apis
interating with sites via selenium for even longer that that. The techniques on this
course will teach you to make and fetch API requests for API testing, using selenium to
interact with a website as a user and extract all the useful information
from this, even from Javascript generated sites, using ``BeautifulSoup``.

* [Contact Details for Webtesting Tools and<EMAIL_ADDRESS>
An essential part of testing any modern web application is "black box testing", sometimes called "fucntional testing".
Interacting with the website as if you were a user. This gives you two insights:

1. What hoops do our users actually have to jump through to use our website, could they
   be easier or bettter designed for a better user experience (UX)?
2. Does our website acutally work! Can users perform the actions they need without bugs!

Finding bugs on your staging website with an automated testing suite using selenium is
*waaaay* less embarrassing than having your customers discover them live on site. Minimal
sets of tests can even be deleloped as "gating checks" for commits to master, making  it
less likely that fundamentlly broken code can be delivered to production.

For for functional tests speed of test run is always a trade-off against how much detail
to test functionality in. This trade-off is one of the things we discuss and consider in
this course.

The same, or similar, tools and techniques can be used for testing web apis.

The Python ecosystem has several powerful tools for working with websites and examining the
results. They can be used both for the testing of web applications and for scraping data
from live websites. Even though they're Python tools they can be used for working with
websites built in any lanugage or system.

The three powerful and easy to learn Python tools for these tasks are:

* [Requests](http://docs.python-requests.org/en/master/)

  A simple and powerful library for handling http requests and responses, including
  full json and authentication support, making it excellent for API testing.

* [Selenium Webdriver](https://selenium-python.readthedocs.io/)

  Selenium provides a very powerful API for communicating from Python with a real
  browser. The full details are very rich and complex, but the basic principles
  are very easy to learn. Selenium works well with dialogs, fully Javascript generated
  sites and sites in iframes.

* [BeautifulSoup](https://www.crummy.com/software/BeautifulSoup/)

  Selenium provides a wonderful way of interacting with websites, but a terrible way
  of looking extesnively into the data they contain and pulling out the useful parts
  in a structured way. Fortunately ``BeautifulSoup`` is excellent for this and plays
  very well with ``Selenium``.

This course teaches these three tools and how to use them together for both powerful
web functional testing, including interacting with all the standard form elements
and even how to use it for a Test Driven Development tool. It also covers pulling out
and organising structured data from webpages, useful for both web testing and web
scraping. It includes looks at both XPATH and CSS queries which are essential for
finding and navigating elements on a web page.

We'll cover the Python csv module for outputting data and as an added bonus we may look
at the combination of [Pandas](https://pandas.pydata.org/pandas-docs/stable/)
and [openpyxl](https://openpyxl.readthedocs.io/en/stable/) for writing data out as Excel
compatible files.

Web Testing  with BeautifulSoup and Selenium
---------------------------------------------

The goal of this day is to teach the principles and nuts and bolts of interacting with
Javascript rendered sites using Python and third party library. By the end of the day attendees will be able to create simple scripts and programs that can visit websites, interact with them by entering search terms and navigating the site, and pull out structured data that can be written to data files on the computer. The advanced details of using CSS selectors and XPATH to pull out the data won’t be covered in full, as these are huge topics, but enough information to work with most websites will be provided. Along the way tips and techniques will be delivered to enable attendees to self-teach and work out for themselves, with a little help from google, more complex scenarios. Sample data will be provided for attendees to wrestle with some moderately complex examples.

BeautifulSoup
-------------

* Making a web request with the requests module
* Making and receiving JSON API requests with requests
* Understanding web pages with BeautifulSoup
* Extracting data by tag and the tag type
* A note about parsers (html_parser, lxml and html5lib)
* Navigating the DOM (Document Object Model)
* Where’s my data? Attributes on tags
* Pulling data out into Python objects and writing it to files

Selenium
--------

* Launching a real browser from Python and the interactive interpreter
* The basic API: navigating a site, finding elements, extracting data
* More advanced interactions: clicking links and buttons, entering text, selecting radio buttons, scrolling into view, iframes (etc)
* Navigating a website from a Python program
* CSS selectors and XPATH. View source is your friend
* Why do we have to wait? Javascript rendered sites, some practical techniques
* Show me the source: how we view real html (the DOM) from a Javascript website

Best of Friends: BeautifulSoup with Selenium
--------------------------------------------

In this section we will pull together what we’ve learned of the Python programming
language, and both BeautifulSoup and selenium to extract structured data from complex
websites.

* Fetching a page with selenium and handling it with BeautifulSoup
* Pulling out data into Python collections and re-structuring the data with simple loops and data processing
* Formatting the data for output and writing files
* Debugging techniques and exploratory sessions
* Further examples of using the selenium API to navigate and interact with websites and using the combination of CSS selectors, XPATH and the BeautifulSoup API to work only with the data we’re interested in
* Better ways to work with structured data using the pandas library and different output formats (optional topic)


text:
# reactphp-discord
ReactPHP Based Discord Bot Library

# Example

Simple example below:

```php
#!/usr/bin/env php
<?php
	require_once(__DIR__ . '/vendor/autoload.php');

	use shanemcc\discord\DiscordClient;
	use React\EventLoop\Factory;

	// Client ID of our bot.
	// (Create a new Application at https://discordapp.com/developers/applications/me)
	$clientID = '123456789123456789';
	$clientSecret = 'abcdefghijklmnopqrstuvwxyz012345';

	// Token for our Bot user for the above application.
	$token = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456';

	// Testing Server and channel. We will send a message here when we start up.
	$testServer = '123456789123456789';
	$testChannel = '123456789123456789';

	// Create the DiscordClient and let the user know how to invite the bot
	$client = new DiscordClient($clientID, $clientSecret, $token);
	echo 'Discord invite link: https://discordapp.com/oauth2/authorize?client_id=' . $clientID . '&scope=bot&permissions=536931328', "\n";

	// If we want to manage our own event loop we can, if we call connect()
	// without having given the bot a LoopInterface it will create and start
	// one itself.
	$loop = React\EventLoop\Factory::create();
	$client->setLoopInterface($loop);

	// Servers are not immediately available when the bot starts up, so wait
	// until we get the GUILD_CREATE message for the server we want to send the
	// test message to.
	//
	// This will also mean we will send the message to the channel as soon as we
	// are first invited to the server (if we are online) rather than failing to
	// send it if we were just trying to send it blind.
	$client->on('event.GUILD_CREATE', function(DiscordClient $client, int $shard, String $event, Array $data) use ($testServer, $testChannel) {
		// Check if this is the server we want.
		if ($data['id'] == $testServer) {
			// Check if the channel is known on the server.
			if ($client->validChannel($testServer, $testChannel)) {
				echo 'Sending test message.', "\n";

				// Send the message
				$client->sendChannelMessage($testServer, $testChannel, 'Bot Started.');
			}
		}
	});

	// We can also respond to things, so lets add an !echo command.
	//
	// We react whenever a message is created and respond to the same channel
	// with a reply.
	$client->on('event.MESSAGE_CREATE', function(DiscordClient $client, int $shard, String $event, Array $data) {
		// Don't respond to our own messages.
		if ($data['author']['id'] == $client->getMyInfo()['id']) { return; }

		// Get the command/message
		$bits = explode(' ', $data['content'], 2);
		if (count($bits) < 2) { return; }
		list($command, $message) = $bits;

		// If the command is the right one, deal with it:
		if (strtolower($command) == '!echo') {
			$message = '<@' . $data['author']['id'] . '>' . ' said: ' . $message;

			// We can respond to either server messages or private messages.
			//
			// Technically private messages are channels but the library deals
			// with them separately as it internally handles opening/closing of
			// channels needed for private messaging and allows us to just send
			// messages to user ids rather than needing to get a channel for
			// them manually.
			if (isset($data['guild_id'])) {
				$client->sendChannelMessage($data['guild_id'], $data['channel_id'], $message);
			} else {
				$client->sendPersonMessage($data['author']['id'], $message);
			}
		}
	});

	// Start a connection.
	// If we didn't pass a LoopInterface then one will be created and started
	// automatically when we do this.
	$client->connect();

	// We manage our own LoopInterface, so start it here.
	$loop->run();
```

# How to handle exceptions
```
        $client->on('DiscordClient.throwable', function (DiscordClient $client, \Throwable $e) {
            echo 'Error: ' . $e->getMessage() . PHP_EOL;
        });
```

repository: ShaneMcC/reactphp-discord

gha_language: PHP

repo_name: ShaneMcC/reactphp-discord