text:
```
                      __
                     |  ]
 _ .--.  ,--.    .--.| |  ,--.   _ .--.
[ `/'`\]`'_\ : / /'`\' | `'_\ : [ `/'`\]
 | |    // | |,| \__/  | // | |, | |
[___]   \'-;__/ '.__.;__]\'-;__/[___]

```

# Raphaël radar chart

## Radar chart implemented with [Raphael.js][raphael]

Works where Raphael.js works (Firefox 3.0+, Safari 3.0+, Chrome 5.0+, Opera 9.5+ and Internet Explorer 6.0+).

Only 2.35 KB (1.01KB gzipped) -very lightweight!

## [Example](http://valve.github.com/g.raphael-radar/example)

## Basic usage

```
var paper = Raphael('some_div_id', 800, 800);
paper.radar(cx, cy, radius, data_array, options);
```

To see real example, have a look at test/index.html

### Options

This chart can be customized by passing the options that will override the default values, for example

```
paper.radar(400, 400, 300, [4, 8, 15, 16, 23, 42],
  {
    meshSize: 30,//the space between adjacent meshes,
    labels: ["USA", "Canada", "Sweden", "Ukraine", "Uzbekistan", "Russia"],
    labelFontSize: 20, //huge font
    drawLabels: true, //to draw labels or not
    armFill: 'none', //color of arm fill
    armStroke: 'rgba(255, 106, 0, .5)', //color of arm stroke
    armStrokeWidth: 1, //width of arm stroke
    drawArms: true, //to draw arms or not
    meshFill: 'none', //color of mesh fill
    meshStroke: 'rgba(120, 120, 120, .5)', //color of mesh stroke
    meshStrokeWidth: 1, //width of mesh stroke
    drawMesh: true, //to draw mesh or not
    max: 100, //maximum value, if not present, calculated from maximum value of data array
    pathFill: 'none', //color of data path fill
    pathStroke: '#0026ff', //color of data path stroke
    pathStrokeWidth: 3, //data path stroke width
    pathCircleOuterRadius: 4, //data path circle outer radius
    pathCircleInnerRadius: 2, // data path circle inner radius
    drawPathCircles: true //whether to draw the circles on the data path
  });
```

### Installation

If you're on Rails, add this line to your gem file:

`
gem 'g.raphael-radar-rails'
`
Then, add a dependency to a sprocket file:

`
//= require 'g.radar'
`

If you're not using rails, just copy the JavaScript to your scripts directory.

### Licence

This code is [MIT][mit] licenced:

Copyright (c) 2012 Valentin Vasilyev

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.

[raphael]: http://raphaeljs.com/
[mit]: http://www.opensource.org/licenses/mit-license.php


text:
# Soarvey
React app that allows you to collect feedback from users with email campaigns.

# Tech Stack
* Node JS
* Express
* React
* Axios
* SendGrid + SendGrid Webhooks
* Mongoose
* MongoDB

# Demo
https://secure-plains-80111.herokuapp.com/

license: MIT

branch_name: refs/heads/master

extension: md

license_type: permissive


text:
# CPC3010 logger
Python utility to read the output from a TSI CPC3010 and optionally control the voltage of a compatible differential mobility analizer (DMA) and upload data to a PostgreSQL database.

The script requests the 1 second buffer from the CPC, timestamps it and saves it to a file. Optionally, it can send the control command to, stepwise, sweep the **full range** of voltage on the DMA in and upload the data to a database.

## Modules required
* **pyserial**
* **psycopg2**
* **time**

## Usage
The settings are specified in the ```settings.txt``` file which should look like:
```
/dev/ttyUSB0
./
local,0
user=datauses password=l3tme1n host=penap-data.dyndns.org dbname=didactic port=5432
408,409,1
SMPS,10
## Only the first lines are processed.
1 <SERIAL PORT ADDRESS>
2 <DATA SAVE PATH>
3 <local/database selector>,<compress data? 1=='yes'>
4 <DATABASE CONNECTION STRING>
5 <DATABASE INSERT IDs>
6 <"SMPS" means the SMPS is connected, number of size bins for scan>
```
Remember that the number of bins refer to the full range of voltage on the SMPS. The scaling is logarithmic and the actual bins are reported in the data file.

There are two scripts to run:
* ```logger_mail.py```. This is the main logging script and the one that interacts directly with the CPC. It must be run manually and it will continue to run until stopped by ```^C```. The outputs from this script are one datafile named ```YYYYMMDD.txt``` with the 1 second data and a ```SQL/inserts.sql```with the SQL statements to update the database with the **1 minute average** data.
* ```upload_batch_sql.py```. This is the **optional** database updater and it it recommended to be run as a cron job every 5 to 10 minutes

For further details contact Gustavo Olivares

## License
MIT. See LICENSE.md for details.


text:
## Test Driven Development using Mocha and Chai frameworks for NodeJS and JavaScript

This repo contains the automated unit tests written using the Mocha and Chai test frameworks for NodeJS and JavaScript.

#### Installation Instructions

1. Install a licensed version of WebStorm IDE.
2. Fork the project and clone it into your directory
3. Install dependencies: node, mocha, chai, request, sinon, sinon-chai, nyc
     ##### npm install dependency_name
4. Run tests using following commands:
     ##### cd tests/testfolder/
     ##### mocha *tests.js
________

###### Now, sit back and relax!!
or
#### Write new tests

If you'd like to add more tests to my shared collection, please open a pull request against master branch

#### Credits

Siddhant Wadhwani

gha_language: JavaScript

gha_license_id: MIT


text:
# D3 - Visualize Data with a Bar Chart
 _A Pen created at CodePen.io. Original URL: [https://codepen.io/maci01/pen/WNbJrEp](https://codepen.io/maci01/pen/WNbJrEp).

extension: markdown


text:
# ACS UPB Mobile - Flutter workshop

This workshop is meant to help you get started with Flutter and contributing to the **ACS UPB Mobile** app. We will be using the app as reference throughout the workshop, so please make sure you follow the steps described [here](https://github.com/acs-upb-mobile/acs-upb-mobile/blob/master/README.md#building-from-source-with-android-studio) to build and run it. The estimated time for completing the workshop is roughly 4h, but it can take longer if you follow the additional resource links. If you feel the time estimates are inaccurate or want to fill in the missing estimates, feel free to open a PR on this repo directly to fix them.

- [Start contributing](#start-contributing)
- [Get started with Flutter](#get-started-with-flutter)
  * [What **is** Flutter?](#what---is---flutter-)
  * [Create a new Flutter application - 10 mins](#create-a-new-flutter-application---10-mins)
  * [Change it up - 10 mins](#change-it-up---10-mins)
  * [Create the layout - 25 mins](#create-the-layout---25-mins)
    + [AppBar](#appbar)
    + [Card](#card)
  * [Add the content - 12 mins](#add-the-content---12-mins)
    + [Import a package - 5 mins](#import-a-package---5-mins)
    + [Use the package - 5 mins](#use-the-package---5-mins)
    + [Check orientation - 2 mins](#check-orientation---2-mins)
  * [Make it interactive - 40 mins](#make-it-interactive---40-mins)
    + [Start with the header - 10 mins](#start-with-the-header---10-mins)
    + [Build the data rows - 20 mins](#build-the-data-rows---20-mins)
    + [Update the datamap - 10 mins](#update-the-datamap---10-mins)
  * [Add another page - 45 mins](#add-another-page---45-mins)
    + [New home page - 13 mins](#new-home-page---13-mins)
    + [Navigating between pages - 7 mins](#navigating-between-pages---7-mins)
    + [Passing data - 25 mins](#passing-data---25-mins)
  * [Test it - 8 mins](#test-it---8-mins)
  * [Make data persistent - 20 mins](#make-data-persistent---20-mins)
    + [Enable the plugin - 5 mins](#enable-the-plugin---5-mins)
    + [Handle the data - 12 mins](#handle-the-data---12-mins)
    + [Fix the tests - 3 mins](#fix-the-tests---3-mins)
  * [Add improvements](#add-improvements)
- [Get started with Firebase](#get-started-with-firebase)
  * [Add Firebase to your app(s)](#add-firebase-to-your-app-s-)
    + [Enable the FlutterFire plugins](#enable-the-flutterfire-plugins)
    + [Add Firebase to Android](#add-firebase-to-android)
    + [Add Firebase to iOS](#add-firebase-to-ios)
    + [Add Firebase to Web and host the app](#add-firebase-to-web-and-host-the-app)
  * [Use Firestore in the app](#use-firestore-in-the-app)
    + [Create the database](#create-the-database)
    + [Update the provider](#update-the-provider)
    + [Update the layout](#update-the-layout)
    + [Check permissions](#check-permissions)

## Start contributing

If you're not familiar with git, consider learning the basics from one of the many resources available online. We recommend [GitHub's resources](https://try.github.io/), particularly the [Git-It](https://github.com/jlord/git-it-electron) hands-on tutorial.

In order to start contributing, simply follow these 10 steps:

1. Please make sure you've read the [CONTRIBUTING.md](https://github.com/acs-upb-mobile/acs-upb-mobile/blob/master/CONTRIBUTING.md) file.
2. Fork the [ACS UPB Mobile](https://github.com/acs-upb-mobile/acs-upb-mobile) repository.
3. Clone the fork onto your system and open it as an Android Studio project.
4. Don't forget to run `flutter pub get` to update the dependencies.
5. Create a new branch by clicking on *Git: master* on the bottom right border in Android Studio and selecting *New Branch*. Its name should succinctly describe the modification/feature you are trying to add, so in this case something like `update_contributors` would be appropriate.
6. Add yourself to the list of contributors in the `README.md` file. The recommended format is: `[FirstName LastName](link_to_github_profile)`.
7. Commit and push the changes to the forked repository (*Ctrl*+*K* for committing, *Ctrl*+*Shift*+*K* for pushing in Android Studio).
8. Create a pull request either from GitHub (you will see a message prompting you to create a PR when you open the forked repository) or Android Studio (VCS > Git > Create Pull Request). Make sure the PR points from the branch you created to the master branch in the acs-upb-mobile repo.
9. Wait for the PR to be approved.
10. Pat yourself on the back.

Once in a while you should sync your fork's master with the upstream (the original repo) master. To do this:
1. In the repo on your machine add a new remote that points to **acs-upb-mobile/master** using the command: `git remote add upstream https://github.com/acs-upb-mobile/acs-upb-mobile.git`.
2. Fetch the data from the upstream repo: `git fetch upstream`.
3. Checkout your fork's `master` branch: `git checkout master`.
4. Merge `upstream` into your fork's `master`: `git merge upstream/master`. This may produce conflicts, unfortunately. To fix them, open the *VCS* menu in Android Studio, select *Git* and *Resolve conflicts*.
5. Push `master` to save the sync to GitHub either by using the Android Studio GUI or by calling `git push origin/master`.

## Get started with Flutter

### What **is** Flutter?

First of all, let's talk a bit about Flutter. It is a cross-platform framework developed by Google, meaning it allows us to use the same codebase for an application that can run on multiple operating systems (iOS, Android, Fuchsia, MacOS etc.) and the web. Flutter uses **Dart** as its main programming language. The Dart syntax is clean and looks similar to Java, while sharing certain useful features with languages like JavaScript and C# (for example, the `async`/`await` combo, with `Future`s in Dart being similar to `Promise`s and `Task`s in JavaScript and C# respectively).

In order to familiarize yourself with Dart, please go through this simple, 20-minute [codelab](https://codelabs.developers.google.com/codelabs/from-java-to-dart/) before proceeding with this workshop.

### Create a new Flutter application - 10 mins

Open Android Studio and create a new Flutter application. The sample app is very well explained through comments and it will help you understand the absolute basics of using Flutter. Analyze the folder structure and carefully read the following files:
- `lib/main.dart`, which is the application itself
- `pubspec.yaml`, which contains metadata necessary for building the application (similar to `build.gradle` in Android or `Info.plist` in iOS)
- `test/widget_test.dart`, a simple test for the sample application

Run the test to make sure it works by right-clicking `widget_test.dart` and selecting `Run`. Run the application and play around with the code in `main.dart`, while taking advantage of the Hot Reload feature, which allows you to load changes in the code quickly into an already running app, without you needing to restart/reinstall it. For example, change the text and colours, reposition the widgets, make the counter count backwards (make sure you fix the test accordingly for that last one) etc.

---
**Optimizing your workspace**

On the left-hand Project panel in Android Studio, make sure you have the *Project* view open in the drop-down (not *Android*).

You can make the emulator window display on top of the IDE by going to Extended controls (...) in the emulator and enabling 'Emulator always on top' in Settings. This is especially useful when playing around with the UI in Flutter, as you will see the application update every time you save, thanks to the Hot Reload feature.

---

---

**Troubleshooting tips**

If Android Studio doesn't work properly (it doesn't highlight the code and errors or make suggestions), it may be a good idea to restart it. Click `File` > `Invalidate Caches / Restart` and hope for the best.

If the app doesn't work as expected, try restarting it (Hot Reload doesn't work with major code/flow changes). If that still doesn't work and you think your code is correct, you can try re-building it from scratch (run `flutter clean` to delete build files and then try `flutter run` or pressing the play button/*Shift*+*F10* again).

Finally, if you see weird errors like classes not getting recognized, make sure Flutter is up to date (run `flutter upgrade`) and you're on the right branch (e.g. `flutter channel beta` if you're using the web version). Additionally, keep your dependencies up to date by running `flutter pub get`.

---

Subsequent sections will link to a tag in this repository which has the code you should end up with at the end of that section. You can use them to skip a section or cross-check your code if you have a problem. Keep in mind that the code snippets in this document are often not complete, since they are only meant to help you understand what you need to do.

The code that corresponds to this section can be found [here](https://github.com/acs-upb-mobile/flutter-workshop/tree/new_app).

### Change it up - 10 mins

Now that we have the basics covered, it's time to code. We'll start by butchering the sample app - first, let's change the colours. Remove the `primarySwatch` attribute from `ThemeData` and set `primaryColor` and `accentColor` to the ones in **ACS UPB Mobile** (*hint*: you can find them [here](https://github.com/acs-upb-mobile/acs-upb-mobile/blob/master/lib/main.dart)). Note what changes in the app with each attribute.

Next, remove `MyHomePage` and `MyHomePageState` entirely. Create a new widget class called `MainPage` to replace it. In Flutter, widgets can be *stateless* or *stateful*. If it can change - for example, when a user interacts with it - it's stateful. Let's make ours a `StatelessWidget` for now, which returns a simple `Scaffold`. Congratulations, you now have an empty Flutter app!

---
**IntelliSense tip #1: missing overrides**

Take advantage of useful Android Studio features. For example, you can press *Alt*+*Enter* and *Create missing overrides* to easily define the `build` method of a new widget.

---

A Flutter app is essentially a *widget tree*. Most widgets don't need to be leaves in the tree, therefore they have a `child` or `children` attribute which allows us to nest other widgets within them. This is somehow similar to *nested tags* in HTML, in that parent widgets can control the appearance and properties of child widgets.

The most important method in a Widget is the `build` method, which describes the part of the UI represented by that widget. This method takes a `BuildContext` parameter, which has information about the location in the tree where the widget builds.

### Create the layout - 25 mins

We will now attempt to create a layout similar to the grading view in **ACS UPB Mobile**:

#### AppBar

The coloured strip at the top is called an `AppBar`. Let's give our `Scaffold` an `AppBar` with a meaningful `title`.

```dart
class MainPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('A meaningful title'),
      ),
    );
  }
}
```

Note the comma at the end, where the `title` attribute is defined - since Flutter widgets have a nested appearance, this optional comma after the last attribute in a widget helps with formatting (*Ctrl*+*Alt*+*L* in Android Studio to reformat the code).

Keep in mind that **ACS UPB Mobile** uses a [custom scaffold](https://github.com/acs-upb-mobile/acs-upb-mobile/blob/master/lib/widgets/scaffold.dart) for consistency throughout pages in the app, meaning you will never need to define the `AppBar` yourself. Whenever you need to create a new page, you will start with an `AppScaffold` instead of a standard `Scaffold`.

#### Card

The styled, elevated container that holds the pie chart in the screenshot above is called a `Card`. Let's try to create an empty card which takes up a third of the available space.

First, for the `Card` to actually be visible in the app, it needs to hold *something*. We won't add the pie chart just yet, but we can use a placeholder for now. The standard way of defining an 'empty' widget is through a `Container` with no attributes set, like this:

```dart
Scaffold(
  appBar: AppBar(
    title: Text('A meaningful title'),
  ),
  body: Card(
    child: Container(),
  ),
)
```

If you save and look closely at the app, you can see the elevated margins of the card which now takes up the whole available space of the scaffold. Now, how do we make it only take up a third of the space? The naïve way would be to directly give it a specific size - the `Container` widget takes a `height` attribute, which we can set like this:

```dart
Card(
  child: Container(
    height: MediaQuery.of(context).size.height / 3,
  ),
)
```

Wait, what? What did we just do there? It's simple, let's take it step by step. You already know that the context defines the current location in the widget tree. The `.of(context)` call, by design, is meant to return an instance of the widget it's used on by going up the tree of the context that is passed. In our case, it returns an instance of `MediaQuery`, which holds information about the size of the current window.

It is important to observe that this call returns the height of the screen itself (taking orientation into account). In other words, the card now takes up a third of the *entire screen*, not the available space in the scaffold. If we want the latter behaviour, we need to substract the height of the AppBar as follows:

```dart
Widget build(BuildContext context) {
  var appBar = AppBar(
    title: Text('A meaningful title'),
  );

  return Scaffold(
    appBar: appBar,
    body: Card(
      child: Container(
        height: (MediaQuery.of(context).size.height -
                appBar.preferredSize.height) / 3,
      ),
    ),
  );
}
```

If this seems complicated, that's because it is. There is a better way to obtain this behaviour, by using a `Column` flex widget.

The two basic layout widgets in Flutter are `Row`s and `Columns`, which take  a list of widgets and position them accordingly. Orientation and alignment are defined by the *main axis* and the *cross axis*, as such:

If we see our desired layout as a column, we want a card that takes up 1/3 of the available space, followed by an empty container that takes up the remaining 2/3. We can achieve this by using the `Expanded` widget's `flex` property like this:

```dart
Scaffold(
  appBar: AppBar(
    title: Text('A meaningful title'),
  ),
  body: Column(
    children: [
      Expanded(
        flex: 1,
        child: Card(child: Container()),
      ),
      Expanded(
        flex: 2,
        child: Container(),
      )
    ],
  ),
)
```

The flex factor is `1` by default, so specifying it for the card is optional. `Expanded` widgets take up all of the available space, and the `flex` attribute dictates how the space is distributed between the siblings.

---

**IntelliSense tip #2: wrapping widgets**

We had to wrap the `Card` in an `Expanded` widget, which in turn was wrapped by a `Column` widget. This happens frequently with Flutter development, and the larger the widget tree becomes, the harder it is sometimes to find the right place to add the appropriate brackets. Android Studio makes it easy - just *Alt*+*Enter* on the name of the widget you'd like to wrap, and select *Wrap with widget*!

---

If we look at the app, the layout is now similar to the grading view's background, except for one detail - there should be some spacing between the card and the edges of the screen. Spacing around a widget is called `Padding`. Let's use *IntelliSense* to quickly wrap the entire `Column` in a `Padding` of 8 pixels!

It should've automatically set the `padding` property to `EdgeInsets.all(8.0)`. This means that we want a padding of 8 pixels on each side of the wrapped widget. We can use `EdgeInsets` to define exactly what kind of padding we want, for example `EdgeInsets.only(left: 8.0, right: 4.0)` to specify a value for each side and omit sides we don't need a padding on, `EdgeInsets.symmetric(vertical: 2.0)` if we want the same padding on corresponding sides, or `EdgeInsets.fromLTRB(1.0, 2.0, 3.0, 4.0)` to specify the padding for each side without needing named parameters (the order is left-top-right-bottom, LTRB).

The code that corresponds to this section can be found [here](https://github.com/acs-upb-mobile/flutter-workshop/tree/basic_layout). You should now have an app that looks like this:

### Add the content - 12 mins

We're ready to add the actual content!

#### Import a package - 5 mins

Even though Flutter is a fairly new technology, the community is very active, and because it is open source there are countless available resources online that you can use. A good rule of thumb is, *don't try to reinvent the wheel*. Before starting to work on something, check if someone has done it before. You might find a useful package that you can add to the app, or maybe even a sample app that you can copy and modify for your needs.

One such example is, in our case, displaying some data in the form of a pie chart in Flutter. The [pie_chart](https://pub.dev/packages/pie_chart) package is just a mere Google Search away. Get used to the resources offered by pub.dev - any package published will have documentation, statistics, instructions and an example usage. And the best part of open source? If the API doesn't quite suit your requirements but you'd like to use parts of a package, you can pretty much always just copy and modify the parts of their code you're interested in. To be safe, you can check the LICENSE file of the project, but generally all Dart packages have either an MIT or BSD license.

---

***Life pro tip:*** If you do fiddle with someone's package, for instance to add functionality or expose some fields, it might be a good idea to even contribute to that package itself. E-mail the owner to tell them what you'd like to do, and if they say it's okay, submit a PR! Open source points on your résumé are always useful.

---

Back to our app - all we need to do to use this package is to add it to our `pubspec.yaml` file under `dependencies`:

```yaml
dependencies:
  pie_chart: <latest version>
```

You can see the latest version in the package's name. Specifying it is not mandatory, but it is recommended. You will often see a caret next to the version specified in pubspec files (e.g. `pie_chart: ^3.1.1`), symbolising "version 3.1.1 or the newest compatible version", or ">=3.1.1 <4.0.0", since a new major version usually implies breaking changes.

Android Studio will prompt you to run `flutter pub get` to update the dependencies of your project. Do so.

#### Use the package - 5 mins

Read the documentation of `pie_chart` and use the simple example to place a pie chart in our `Card`.

  Spoiler - solution

  ```dart
  Widget build(BuildContext context) {
    Map<String, double> dataMap = new Map();
    dataMap.putIfAbsent("Flutter", () => 5);
    dataMap.putIfAbsent("React", () => 3);
    dataMap.putIfAbsent("Xamarin", () => 2);
    dataMap.putIfAbsent("Ionic", () => 2);

    return Scaffold(
      appBar: AppBar(
        title: Text('A meaningful title'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(8.0),
        child: Column(
          children: [
            Expanded(
              flex: 1,
              child: Card(child: PieChart(dataMap: dataMap,)),
            ),
            Expanded(
              flex: 2,
              child: Container(),
            )
          ],
        ),
      ),
    );
  }
  ```

Normally, we shouldn't do complex operations like populating a dataset in the build method, because *it is called every time the page is reloaded or something changes*. This is particularly important for stateful widgets, which are rebuilt often.

#### Check orientation - 2 mins

Hot Reload and look at the app. Now we have the pie chart and it looks alright! However, check what happens if you rotate the device. You will most likely see an overflow. Can you tell why it happens?

  Spoiler - answer

  The card's height is a third of the available height - which, in landscape mode, is the screen's width. This isn't enough to fit the entire content of the pie chart, and the package doesn't know how to deal with not having enough space.

Note that the ugly overflow warning is only visible in debug mode, for the developer to notice. In release mode, the user simply won't see the part of the widget that overflowed.

---

**Build modes**

Flutter offers three build modes:
- *debug mode*, used during development, allows the usage of IDE debugging tools and hot reload
- *profile mode* is used when you want to analyze performance
- *release mode* is the version seen by the end user

The performance in debug mode is almost always worse than the other two modes. Release mode cannot be used on an emulator, but if you want to take nice screenshots you can disable the debug banner from the *Flutter Inspector* tab found on the right edge of Android Studio.

---

Layout issues can usually be solved by either defining the layout differently (we've already seen that the same thing can be done in multiple ways in Flutter) or using a different layout for landscape and portrait with an [`OrientationBuilder`](https://api.flutter.dev/flutter/widgets/OrientationBuilder-class.html).

Let's change the layout yet again to fix the overflow. The easiest way is to replace the `Column` with a `ListView`, which is essentially a scrollable column. We can simply replace the word 'Column' with 'ListView' and the app will work... but if we look at the console, we will see an exception:

Flutter errors are very verbose and, more often than not, will offer the exact solution to the problem and an explanation. In our case, it tells us that an `Expanded` widget can only be within a `Flex` widget (usually a `Row` or `Column` widget). We can just remove the `Expanded` widgets now and let the pie chart package control the size of the card on its own.

---

**IntelliSense tip #3: removing widgets**

Similar to wrapping widgets, we can also remove them easily from the tree using Android Studio. Press *Alt* + *Enter* while the cursor is on the name of any widget that has exactly one child, and you will get the option to remove it:

---

The code that corresponds to this section can be found [here](https://github.com/acs-upb-mobile/flutter-workshop/tree/content). The app should now look like this:

### Make it interactive - 40 mins

We want the user to be able to change the values of the items in the datamap, so we'll make an editable table containing two columns: *Name* (not editable) and *Value* (editable).

#### Start with the header - 10 mins

Let's add a header just under the card, with the *Name* label taking up 3/4 of the horizontal space, and the *Value* label the other 1/4 (*hint*: the wigets you need are `Row`, `Expanded` and `Text`). We should give it a padding as well - the standard 8 pixels on each side looks good.

The `Text` widget takes a `style` argument, which allows us to control the colour, size, font and weight of the text. You could manually set these properties, but for consistency in an app, it is generally recommended to use pre-defined styles from the app's theme. You can define these globally in the same place where you defined the primary and secondary colours earlier. For our header, we could use the `headline6` text style, which you can obtain by calling `Theme.of(context).textTheme.headline6`, similar to how you used `MediaQuery` to get the screen size before. This is particularly important with apps with a customizable theme, like **ACS UPB Mobile** which has a dark mode and a light mode.

It should now look like this:

  Spoiler - solution

  ```dart
  ListView(
    children: [
      Card(child: PieChart(dataMap: dataMap)),
      Padding(
        padding: const EdgeInsets.all(8.0),
        child: Row(
          children: [
            Expanded(
              flex: 3,
              child: Text(
                "Name",
                style: Theme.of(context).textTheme.headline6,
              ),
            ),
            Expanded(
              child: Text(
                "Value",
                style: Theme.of(context).textTheme.headline6,
              ),
            ),
          ],
        ),
      ),
    ],
  )
  ```

Keep in mind that, since **ACS UPB Mobile** is localized (works in both English and Romanian), you will never have to type string literals in the code itself, since everything needs to be defined in both languages in the localization files. The [Flutter Intl](https://plugins.jetbrains.com/plugin/13666-flutter-intl) Android Studio plugin generates localization code automatically, so make sure you have it installed. Say we need to define the strings for "Name" and "Value" - we would need to define them in [intl_en.arb](https://github.com/acs-upb-mobile/acs-upb-mobile/blob/master/lib/l10n/intl_en.arb) and [intl_ro.arb](https://github.com/acs-upb-mobile/acs-upb-mobile/blob/master/lib/l10n/intl_ro.arb) (the plugin fires automatically when we save an .arb file), and then use them in the code as `S.of(context).name` and `S.of(context).value`.

#### Build the data rows - 20 mins

Now, we need to add a row for each entry in the datamap. To keep things clean, create a method (`List<Widget> buildTextFields(Map<String, double> dataMap, BuildContext context)`) in the `MainPage` class, that generates a row with two `TextFormField` widgets for each (key, value) pair in the map. We only want to modify the values, so make the field that corresponds to the key (the name) `readOnly`. The value field should only accept numerical values (*hint*: check the `keyboardType` attribute).

For a nicer look, you can add some padding to these rows and some spacing between the columns (don't forget the header). Padding between list items can be added using a `SizedBox` instead of a `Padding` widget, if you want to avoid unnecessary nesting.

  Spoiler - possible solution

  ```dart
  List<Widget> buildTextFields(
      Map<String, double> dataMap, BuildContext context) {
    return dataMap
        .map(
          (key, value) => MapEntry(
              key,
              Padding(
                padding: const EdgeInsets.symmetric(horizontal: 8.0),
                child: Row(
                  children: [
                    Expanded(
                      flex: 3,
                      child: TextFormField(
                        initialValue: key,
                        readOnly: true,
                      ),
                    ),
                    SizedBox(width: 16.0),
                    Expanded(
                      child: TextFormField(
                        initialValue: value.toString(),
                        keyboardType:
                            TextInputType.numberWithOptions(decimal: true),
                      ),
                    ),
                  ],
                ),
              )),
        )
        .values
        .toList();
  }
  ```

Concatenate the result to the end of the `ListView`'s children, before the comma (`ListView(children: [...] + buildTextFields(dataMap, context),)`) and you should now have a table that looks like this:

#### Update the datamap - 10 mins

You can now modify the values in the second column, but the datamap doesn't get updated. To update it, we should define the `TextFormField`'s `onChanged` callback. Add a `print` statement to make sure it gets called correctly.

```dart
TextFormField(
  initialValue: value.toString(),
  keyboardType:
      TextInputType.numberWithOptions(decimal: true),
  onChanged: (newString) {
    double newValue = double.tryParse(newString) ?? 0.0;
    dataMap[key] = newValue;
    print(key + ': ' + newValue.toString());
  },
)
```
Now, if we look at the console we can see it does get called when a value is changed, but the pie chart remains unchanged. Can you guess why that is?

  Spoiler - answer

  Our widget is stateless. It is built once and never gets updated, meaning that if the datamap changes afterwards, the widget won't be rebuilt. We need a stateful widget for this.

---

**IntelliSense tip #4: stateless to stateful**

Android Studio to the rescue again! It's easy to convert a stateless widget into a stateful one - just *Alt*+*Enter* on the name of the widget!

---

Alongside the `build` method, which is called every time the widget is updated, stateful widgets have an `initState` method that is called on the first build. Let's make the `dataMap` a class attribute and initialize it in `initState` **instead of** `build`:

```dart
class _MainPageState extends State<MainPage> {
  Map<String, double> dataMap;

  @override
  void initState() {
    super.initState();

    dataMap = new Map();
    dataMap.putIfAbsent("Flutter", () => 5);
    dataMap.putIfAbsent("React", () => 3);
    dataMap.putIfAbsent("Xamarin", () => 2);
    dataMap.putIfAbsent("Ionic", () => 2);
  }

  @override
  Widget build(BuildContext context) {
    ...
  }
```

When we change the state (in our case, by updating the data map), we need to notify the framework to process the change. We do this by making the change in a function that is passed to `setState`. The last thing we need to do for our pie chart to be interactive is to make a slight modification to the `onChanged` callback of our text fields:

```dart
onChanged: (newString) {
  double newValue = double.tryParse(newString) ?? 0.0;
  setState(() {
    dataMap[key] = newValue;
  });
  print(key + ': ' + newValue.toString());
}
```

We can now change the value of the items in the data map and watch the pie chart update as we do that. Please keep in mind that the Hot Reload functionality does not work with major changes such as making a widget stateful. In order to run the app, rebuilding is necessary. The code that corresponds to this section can be found [here](https://github.com/acs-upb-mobile/flutter-workshop/tree/interactive). The app should now look like this and be interactive:

### Add another page - 45 mins

Now, what do we do if we want to have another page? And more importantly, what do we do if we want to share data between those pages?

Say we want our home page to contain just the chart, centered and with the legend placed at the top. On the right side of the scaffold, we'd have an edit button that takes us to the page we've already build.

#### New home page - 13 mins

Let's rename our stateful widget to `EditPage` and create a new `MainPage` widget with the characteristics above. Leave out the edit button for now. You can put each of them in their own file to avoid having a very large `main.dart` file. You can also change the title on the app bar for each of them accordingly ('View chart'/'Edit chart').

  Spoiler - solution

  ```dart
  class MainPage extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
      Map<String, double> dataMap = new Map();
      dataMap.putIfAbsent("Flutter", () => 5);
      dataMap.putIfAbsent("React", () => 3);
      dataMap.putIfAbsent("Xamarin", () => 2);
      dataMap.putIfAbsent("Ionic", () => 2);

      return Scaffold(
        appBar: AppBar(
          title: Text('View chart'),
        ),
        body: PieChart(
          dataMap: dataMap,
          legendPosition: LegendPosition.top,
        ),
      );
    }
  }
  ```

#### Navigating between pages - 7 mins

Now, we need to add the edit button to the scaffold's app bar. This is done by adding an `IconButton` as an `action` to the `AppBar`. The `onPressed` callback on this button uses `Navigator` to open an `EditPage`.

```dart
AppBar(
  title: Text('View chart'),
  actions: [
    IconButton(
      icon: Icon(Icons.edit),
      onPressed: () => Navigator.of(context)
          .push(MaterialPageRoute(builder: (context) => EditPage())),
    )
  ],
)
```

The pages in an app act like a stack - if we `push` a new page, the user can navigate back to the previous page in the stack by pressing the back button (equivalent to `pop`ping the stack). We have full control of the stack with various `Navigator` methods - for instance, if we want to replace the current page, we can use `pushReplacement`.

Alternatively, a cleaner way to deal with navigation is through *named routes*. Replace `home: MainPage()` in the `MaterialApp` with:

```dart
routes: {
  '/': (context) => MainPage(),
  '/edit': (context) => EditPage(),
}
```

The default route when the app opens is '/', but you can specify a different one using `initialRoute`, should you need to. You can now open the edit page by simply calling:
```dart
Navigator.of(context).pushNamed('/edit')
```

An interesting effect of using named routes is that they are accessible through the URL in the web version. Try running the app on the web, by selecting "Chrome (web)" from the device dropdown. You will notice that, if the URL is, for instance, 'http://localhost:52755/#/', you can access 'http://localhost:52755/#/edit' to get to the edit page.

#### Passing data - 25 mins

Right now, each page uses a separate data map. If we used `MaterialPageRoute` and built the `EditPage` instance in the `MainPage` to navigate, we could technically pass the data map as a parameter to `EditPage`'s constructor. However, changes made on the edit page would still not be visible on the main page, since we couldn't notify the main page of the changes. There are multiple ways to handle this, but **ACS UPB Mobile** uses the [provider](https://pub.dev/packages/provider) package.

`Provider` is a dependency injection framework which can be used to manage state in a Flutter application. `Provider`s offer an easy way to encapsulate state and share it with a branch of the widget tree. It achieves that by being defined as the parent of that branch.

Install the [provider](https://pub.dev/packages/provider) package (don't forget to run `flutter pub get`) and create a new source file called `data_provider.dart` in the `lib/` folder. Define the `DataProvider` class here, like this:

```dart
class DataProvider with ChangeNotifier {
  Map<String, double> _dataMap;

  DataProvider() {
    _dataMap = new Map();
    _dataMap.putIfAbsent("Flutter", () => 5);
    _dataMap.putIfAbsent("React", () => 3);
    _dataMap.putIfAbsent("Xamarin", () => 2);
    _dataMap.putIfAbsent("Ionic", () => 2);
  }

  Map<String, double> get dataMap => _dataMap;

  set dataMap(Map<String, double> newDataMap) {
    _dataMap = newDataMap;
    notifyListeners();
  }
}
```

It initialized the data map that we know in the constructor, and has a custom getter and setter - with the setter calling `notifyListeners()` to notify any widget that is using this `Provider` about the change.

---

**IntelliSense tip #5: auto import**

When using a class for a first time in a file, you need to specify the library you want to import it from (be it part of the framework, a package, or your own codebase). You never need to actually remember the library because Android Studio gives you options to import when you start typing the class name, like with the `ChangeNotifier` we just used:

Just select the right option (look at the package name on the right side) and press *Tab* or *Enter* to confirm, and Android Studio will automatically add a line like `import 'package:flutter/foundation.dart';` to the beginning of the file. If you want to order the imports (alphabetically), you can press *Ctrl*+*Alt*+*O*.

Note that some framework components, like `ChangeNotifier`, can be found in multiple libraries. The one you choose to import won't affect the functionality, but we usually prefer to go with the narrow-scope libraries if possible. In this case, the rule of thumb would be:
*`foundation.dart` (Core Flutter framework) > `widgets.dart` (Flutter widgets framework) > `material.dart` (Android-like/Material Design components, used most often in **ACS UPB Mobile**) > `cupertino.dart` (iOS design components)*

---

Now add the provider you created to the root of the application:

```dart
void main() {
  runApp(ChangeNotifierProvider(
      create: (context) => DataProvider(), child: MyApp()));
}
```

There are different types of `Provider`s, but `ChangeNotifierProvider` is the right one for our needs. Now, to fetch this data map from the provider in both of our pages, we simply need to call:

```dart
Provider.of<DataProvider>(context).dataMap;
```

The `<DataProvider>` type specification is optional because we only have one `Provider` as the parent, but becomes necessary when there are multiple `Provider`s in the tree. Finally, we should add a 'Save' button to the edit page which registers the changes with our `DataProvider`:

```dart
class _EditPageState extends State<EditPage> {
  Map<String, double> dataMap;

  @override
  void initState() {
    super.initState();
    dataMap = Provider.of<DataProvider>(context, listen: false).dataMap;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Edit chart'),
        actions: [
          FlatButton(
            child: Text('Save'),
            onPressed: () {
              Provider.of<DataProvider>(context, listen: false).dataMap =
                  dataMap;
              Navigator.of(context).pop();
            },
          ),
        ],
      ),
      body: ...
  }

  ...
}
```

The `listen: false` attribute tells the provider that the particular context in which it is used does not need to listen for changes. In our case, the Edit page does not need to listen for changes, but the main page does (`listen` is `true` by default, so we don't need to specify it when using the Provider there). The code that corresponds to this section can be found [here](https://github.com/acs-upb-mobile/flutter-workshop/tree/pages). If you did everything correctly, the pie chart on the main page should now be updated when you press 'Save' on the edit page. After rebuilding the app and running it, you should see something like this:

---

**BLoC**

**ACS UPB Mobile** uses a variation of the **BLoC** (Business Logic Component) design pattern used in Flutter development. This variant utilizes `Provider`s to avoid boilerplate code.

With BLoC, every page in the app will have three components:

- the *UI/Flutter layer*, also called the *view*, which acts as a middleman between the user and the BLoC layer (in this workshop, the `MainPage` and `EditPage`)
- the *BLoC layer*, which we also refer to as the *Provider* or *service*, contains the actual business logic and communicates with the database (in this workshop, the `DataProvider`)
- the *data layer* or the data *model* contains simple data classes which represent the data that is to be displayed in the UI, and is provided by the BLoC (in this workshop, we don't need a custom class because we simply use a `Map<String, double>` as our model)
---

### Test it - 8 mins

Now we have the functionality we wanted, but we've only tested it manually. Let's add some automated testing in the `test/widget_test.dart` file.

The simplest thing to test is the existence of the legend labels for the pie chart:

```dart
testWidgets('Test names', (WidgetTester tester) async {
  await tester.pumpWidget(ChangeNotifierProvider(
      create: (context) => DataProvider(), child: MyApp()));

  expect(find.text('Flutter'), findsOneWidget);
  expect(find.text('React'), findsOneWidget);
  expect(find.text('Xamarin'), findsOneWidget);
  expect(find.text('Ionic'), findsOneWidget);
});
```

Note that, when pumping the app, you need to pump it with the appropriate `Provider`. Another thing we can test easily is navigation:

```dart
testWidgets('Test navigation', (WidgetTester tester) async {
  await tester.pumpWidget(ChangeNotifierProvider(
      create: (context) => DataProvider(), child: MyApp()));

  expect(find.byType(MainPage), findsOneWidget);
  expect(find.byType(EditPage), findsNothing);

  await tester.tap(find.byIcon(Icons.edit));
  await tester.pumpAndSettle();

  expect(find.byType(MainPage), findsNothing);
  expect(find.byType(EditPage), findsOneWidget);

  await tester.tap(find.text('Save'));
  await tester.pumpAndSettle();

  expect(find.byType(MainPage), findsOneWidget);
  expect(find.byType(EditPage), findsNothing);
});
```

Remember that, after actions like tapping certain buttons, you need to wait for the animations to finish by calling `await tester.pumpAndSettle()`.

Now, right-click `widget_test.dart` and select *Run > tests in widget_test...* to make sure the tests work. If you don't see that option, you may need to *Edit configurations* and add a Flutter Test configuration for the `test/` folder.

To test that the most important feature - editing the chart data - actually works, we first need to initialise the `DataProvider` and test the initial values:

```dart
DataProvider provider = DataProvider();
Map<String, double> dataMap = provider.dataMap;

expect(dataMap['Flutter'], equals(5));
expect(dataMap['React'], equals(3));
expect(dataMap['Xamarin'], equals(2));
expect(dataMap['Ionic'], equals(2));
```

Then , we pump the app, open the edit page, change the value in one of the fields and press 'Save':

```dart
await tester.pumpWidget(
    ChangeNotifierProvider(create: (context) => provider, child: MyApp()));

await tester.tap(find.byIcon(Icons.edit));
await tester.pumpAndSettle();

Finder flutterValueField = find.widgetWithText(TextFormField, '5.0');
await tester.enterText(flutterValueField, '10');

await tester.tap(find.text('Save'));
await tester.pumpAndSettle();
```

Finally, we test the new values:

```dart
expect(dataMap['Flutter'], equals(10));
expect(dataMap['React'], equals(3));
expect(dataMap['Xamarin'], equals(2));
expect(dataMap['Ionic'], equals(2));
```

Run this last test as well to make sure everything works as expected. The code that corresponds to this section can be found [here](https://github.com/acs-upb-mobile/flutter-workshop/tree/testing).

---

**GitHub Actions**

**ACS UPB Mobile** uses GitHub Actions for continuous integration & continuous deployment. What this means is, with every push to the repository, the tests are run in a virtual machine and the last commit pushed will be marked with a checkmark if the tests pass and an x if at least one test fails. If a new tag is added and the tests pass, the new version is automatically deployed onto the website and as an apk on GitHub.

Ideally, every new feature should have its own tests or at least be added to the [integration test](https://github.com/acs-upb-mobile/acs-upb-mobile/blob/master/test/integration_test.dart), which runs on both orientations and multiple screen sizes and navigates to all pages in the app to make sure there are no obvious errors like overflows.

---

### Make data persistent - 20 mins

Our app is now interactive and we can modify the chart data as we please. However, these modifications are not persistent - they are lost if we restart the app. The go-to way to persist data is by using a database (e.g. [SQLite](https://flutter.dev/docs/cookbook/persistence/sqlite), [Hive](https://medium.com/@alexawaikin/hive-for-flutter-fast-local-storage-database-made-with-dart-167ad63e2d1) or [Firebase](https://flutter.dev/docs/development/data-and-backend/firebase), see section [Get started with Firebase](#get-started-with-firebase)), but for very simple data such as ours, we can store key-value data on the disk using the [`shared_preferences`](https://pub.dev/packages/shared_preferences) plugin. It works by wrapping platform-specific persistent storage for simple data (`NSUserDefaults` on iOS and macOS, `SharedPreferences` on Android, etc.).

#### Enable the plugin - 5 mins

**ACS UPB Mobile** uses the [`preferences`](https://pub.dev/packages/preferences) plugin (which in turn depends on `shared_preferences`) to store simple data such as settings. Let's use this in our app as well, add the dependency to the `pubspec.yaml` file.

As per the package documentation, you need to call `PrefService.init()` before running the app. Change the main method to:
```dart
import 'package:preferences/preferences.dart';

void main() async {
  await PrefService.init();

  runApp(ChangeNotifierProvider(
      create: (context) => DataProvider(), child: MyApp()));
}
```
Because the `PrefService.init()` call is asynchronous, we need to use the `await` keyword to make sure it completes before the `runApp` call. The `await` keyword can only be used in asynchronous functions, hence why we need to mark `main` as `async`. If we don't use `await`, the `runApp` call would be made while the `PrefService.init()` method is still running.

---

**Asynchronous programming in Dart**

Dart makes asynchronous programming easier with `async`/`await` and `Future`s. Asynchronous operations let your program complete work while waiting for another operation to finish. This is particularly important when handling UI - the interface operations need to be handled on the main thread for the app to run smoothly, while more complex operations such as network calls and reading from files should be handled in a background thread.

***Key terms:***
- **synchronous operation**: A synchronous operation blocks other operations from executing until it completes.
- **asynchronous operation**: Once initiated, an asynchronous operation allows other operations to execute before it completes.
- **`async`**: You can use the `async` keyword before a function’s body to mark it as asynchronous.
- **`await`**: You can use the `await` keyword to get the completed result of an asynchronous expression. The await keyword only works within an async function.
-**future**: A future is an instance of the `Future` class. A future represents the result of an asynchronous operation, and can have two states: *uncompleted* or *completed*.

To understand asynchronous programming in Dart, consider completing [this 50-minute codelab](https://dart.dev/codelabs/async-await).

---

#### Handle the data - 12 mins

The `shared_preferences` plugin only allows for the following data types to be stored under a key: `bool`, `double`, `int`, `String`, `List<String>`. Because we'd like to store a `Map<String, double>`, we could store it as two string lists. Note that **you should never do this with more complex data**, as it adds the overhead of converting between collections, when the whole point of `Map`s in general is to be very fast.

To set the default values we've been using so far, add the following in your `main` function, after the initialization:

```dart
PrefService.setDefaultValues({
    'data_map_keys': ['Flutter', 'React', 'Xamarin', 'Ionic'],
    'data_map_values': ['5', '3', '2', '2'],
  });
```

If you try to run the app now, you will get an error. As is often the case with Flutter, the error tells you exactly what to do to fix it: you need to add `WidgetsFlutterBinding.ensureInitialized();` as the first line in your `main` function.

Now we need to change our `Provider` to use the new way to save data. This being very easy to do is one of the most important benefits of providers. First, instead of initialising the map, the constructor should now read it from the preferences:

```dart
DataProvider() {
    var keys = PrefService.get('data_map_keys');
    var values = PrefService.get('data_map_values');

    _dataMap = Map<String, double>.from(keys.asMap().map(
        (index, key) => MapEntry(key, double.tryParse(values[index] ?? 0))));
  }
```

Second, we need to update the custom setter:

```dart
set dataMap(Map<String, double> newDataMap) {
    _dataMap = newDataMap;

    PrefService.setStringList(
        'data_map_keys', List<String>.from(_dataMap.keys));
    PrefService.setStringList('data_map_values',
        List<String>.from(_dataMap.values.map((value) => value.toString())));

    notifyListeners();
  }
```

We need the `Iterable<T>.from` calls to convert between different types of iterables (`Map`s, `List`s). If you try to run the app without these calls, you will get type errors.

Run the app - it should work the same way as before, except if you close it and open it again, the changes will still be there.

#### Fix the tests - 3 mins

Every time you change something or do something new, you need to remember to run the tests before committing to the repository. If we try to run our tests now, they will fail because `PrefService` was not initialised.

In Flutter testing, we can use `setUp` to define some code that needs to run before each test (or `setUpAll` for code that needs to run once before all tests). Add the following code to `widget_test.dart` to make the tests pass again:

```dart
setUp(() {
  WidgetsFlutterBinding.ensureInitialized();
  PrefService.enableCaching();
  PrefService.cache = {};
  PrefService.setStringList(
      'data_map_keys', ['Flutter', 'React', 'Xamarin', 'Ionic']);
  PrefService.setStringList('data_map_values', ['5', '3', '2', '2']);
});
```

Congratulations, you now have a fully functional, interactive pie chart app with persistent data! You can find the code [here](https://github.com/acs-upb-mobile/flutter-workshop/tree/persistence).

### Add improvements

You can keep playing around with the app to learn more about Flutter development. Here are some suggestions on what you could do:

- When you press enter on one field on the edit page, change focus to the following field (*hint*: `FocusNode`).
- Add a "Total" field on the edit page (check out the grading view screenshot in the [Create the layout](#create-the-layout) section; the only new widget you would need to copy that layout is `Divider`).
- Make it so you can change keys in the data map as well, not just the values.
- Add a way for users to add new entries in the data map. There are at least two ways to do that:
  + Add a plus button (maybe a `FloatingActionButton`) that makes a new row of text fields appear.
  + Make a new, empty row of text fields appear if both fields in the last row have data in them.
- Add [form validation](https://flutter.dev/docs/cookbook/forms/validation) to make sure the data in the text fields has the format you want (e.g. non-zero numbers for the values, maybe check that the names are capitalized etc.)

Be creative, and remember to update the tests accordingly!

## Get started with Firebase

**ACS UPB Mobile** uses [Firebase](https://firebase.google.com/) services for analytics ([Google Analytics](https://firebase.google.com/docs/analytics)), authentication ([Firebase Auth](https://firebase.google.com/products/auth)) and storage ([Firestore](https://firebase.google.com/products/firestore), [Cloud Storage](https://firebase.google.com/docs/storage)). In order to get familiar with it, this section will guide you through the process of adding and using Firebase in your app. If you skipped the previous section, you can start with the code [here](https://github.com/acs-upb-mobile/flutter-workshop/tree/testing).

 Give it a name (like "Flutter workshop") and enable Google Analytics (you may need to create a Google Analytics account - you can call it "Personal projects" and reuse it whenever you'd like to play around with Firebase). When creation is complete, you will need to add it to your Flutter app on each individual platform (Android, iOS and Web).

#### Enable the FlutterFire plugins

The easiest way to access Firebase services in Flutter is by making use of [`flutterfire`](https://github.com/FirebaseExtended/flutterfire) plugins, which provide an easy-to-use API for Flutter applications. **ACS UPB Mobile** currently uses [`firebase_analytics`](https://pub.dartlang.org/packages/firebase_analytics), [`firebase_auth`](https://pub.dartlang.org/packages/firebase_auth), [`cloud_firestore`](https://pub.dartlang.org/packages/cloud_firestore) and [`firebase_storage`](https://pub.dartlang.org/packages/firebase_storage), all of which depend on [`firebase_core`](https://pub.dev/packages/firebase_core). These packages offer many useful features for all three target platforms (Android, iOS, Web), except `cloud_firestore`, which (as of July 2020) still [lacks Web support](https://github.com/flutter/flutter/issues/45294).

Add the most recent versions of `firebase_core`, `firebase_analytics` and `cloud_firestore` to the project's `pubspec.yaml` file. Remember to run `flutter pub get`.

#### Add Firebase to Android

- Click the Android icon in the Firebase console  to launch the setup workflow. You can find the Android package name in your Flutter project's `android/app/build.gradle` file if you search for the `applicationId` field.
- Download `google-services.json` and save it in the `android/app/` folder.
- Follow the instructions to enable Firebase for the Android app.
- Update `minSdkVersion` in the app-level `build.gradle` file to `21`.
- You may need to run `flutter clean` and re-build the application for the verification step.
- In the Android Studio console, run `flutter packages get`.

*Note*: If you get an error saying "Plugin project :firebase_auth_web not found. Please update settings.gradle.", try the fix [here](https://github.com/FirebaseExtended/flutterfire/issues/2599).

#### Add Firebase to iOS

Skip this step if you do not have a MacOS computer.

- Click "Add app" in the Firebase console and select "iOS" to launch the setup workflow. The bundle ID should be the same as the `applicationId` you used earlier for the Android setup, or you can find it in `ios/Runner.xcodeproj/project.pbxproj` if you search for `PRODUCT_BUNDLE_IDENTIFIER`.
- Download `GoogleService-Info.plist` and save it in the `ios/Runner` folder.
- Follow the instructions to enable Firebase for the Android app. You may need to run `flutter clean` and re-build the application for the verification step.
- In the Android Studio console, run `flutter packages get`.

#### Add Firebase to Web and host the app

- Click "Add app" in the Firebase console and select "Web" to launch the setup workflow.
- Enable hosting. You can keep the default domain name.
- Follow the instructions and add the scripts to `web/index.html` in your project **before the "main.dart.js" script**.
- Run `flutter build web` before following the hosting instructions. Make sure you select `build/web` as the public directory when running `firebase init`:

- You can now access the link and the app should be up and running on the internet! However, if you try to run it locally from Android Studio, you will get an error. Some additional setup is needed to fix that:
  + From the Firebase console, open the settings for the web application.
  + Under *Firebase SDK snippet*, select *CDN*. Replace the scripts you added earlier with this version.
- We will use Firestore as our database for the app. To add the dependency, simply duplicate the `".../firebase-analytics.js"` script line (*Ctrl*+*D* in Android Studio) from `index.html` and change `analytics` to `firestore`.

Your code should now look like [this](https://github.com/acs-upb-mobile/flutter-workshop/tree/firebase), but keep in mind you should use your own configuration. The Firebase console offers all sorts of useful information about your app(s), including usage statistics.

### Use Firestore in the app

#### Create the database

Time to create our Firestore instance. Go to the Firebase console and open the *Database* view from the *Develop* category. Click *Create database*, select *Start in production mode* and choose a location for the cloud resource (the closer to the userbase, the better).

---

**Firestore and its data model**

[Cloud Firestore](https://firebase.google.com/docs/firestore) is a noSQL database that organises
its data in *collections* and *documents*.

**Collections** are simply a list of documents, where each document has an ID within the collection.

**Documents** are similar to a JSON file (or a C `struct`, if you prefer), in that they contain
different fields which have three important components: a ***name*** - what we use to refer to the
field, similar to a dictionary key -, a ***type*** (which can be one of `string`, `number`,
`boolean`, `map`, `array`, `null` - yeah *null* is its own type -, `timestamp`, `geopoint`,
`reference` - sort of like a pointer to another document), and the actual ***value***, the data
contained in the field.
In addition to fields, documents can contain collections... which contain other documents... which
can contain collections, and so on and so forth, allowing us to create a hierarchical structure
within the database.

More information about the Firestore data model can be found
[here](https://firebase.google.com/docs/firestore/data-model).

---

After the database is initialized, create a collection (you can call it 'data' or whatever you want) with a single document (you can allow Firebase to give it an automatic unique ID) containing the data map we've been using so far, containing number fields.

#### Update the provider

Time to update the `Provider` once again, this time to use our cloud-based database. We no longer need the `preferences` plugin and its setup, but we can keep it in the app in case we want to use it for something else.

We no longer need to initialize something in the constructor, so we can delete it. We will create two async methods for fetching and updating the data in the database.

In order to fetch the information, we use the name of the collection and the `documentID` and `await` for the network response. We then extract the `data_map` field from the response and convert it to a `Map<String, double>`.

```dart
Future<Map<String, double>> fetchDataMap() async {
  DocumentSnapshot snap =
      await _db.collection('data').document('vztH0rlKnqYCOyzK11HS').get();

  _dataMap = Map<String, double>.from(snap.data['data_map']
      .map((key, value) => MapEntry(key, value.toDouble())));

  notifyListeners();

  return _dataMap;
}
```

Conversion is relatively easy to do because Firebase stores data as maps and our data model is a simple `Map`. For custom data classes, you would need to implement a way to convert between an instance of the class and a `DocumentSnapshot` or a map. **ACS UPB Mobile** does that by creating `extension`s on the data classes with methods like `fromSnap` and `toData` (a good example is [here](https://github.com/acs-upb-mobile/acs-upb-mobile/blob/master/lib/pages/portal/service/website_provider.dart)). Extensions extend the functionality of a class by adding new attributes, constructors or methods. They are usually made on classes you cannot modify (such as pre-defined classes like `StatelessWidget` or even `String`), but in our case help with the separation of concerns. The data layer should not have any database-specific functionality (as per the design pattern we described in the [Passing data](#passing-data) section), hence why we define this behavior in the service layer (our provider).

The process of updating data is fairly similar:

```dart
void updateDataMap(Map<String, double> newDataMap) async {
  DocumentReference ref =
      _db.collection('data').document('vztH0rlKnqYCOyzK11HS');

  await ref.updateData({'data_map': newDataMap});
}
```

Our setter will now call `updateDataMap` instead of updating the preferences. We won't bother waiting for it, but depending on the situation, in other apps you may want to wait and report an error if it occurs. You could, for instance, wrap the call in a `try`/`catch` block.

```dart
set dataMap(Map<String, double> newDataMap) {
  _dataMap = newDataMap;
  updateDataMap(newDataMap);
  notifyListeners();
}
```

The `dataMap` field now acts as a simple in-memory cache. It will be `null` if `fetchDataMap` was not called successfully, therefore we must change `MainPage` to make sure it does call it.

#### Update the layout

Flutter has a very useful widget for dealing with futures, called a `FutureBuilder`. It can display something different depending on whether the future is complete or not. We will use it as the body of our scaffold, and make it display a progress indicator while waiting for the data, a pie chart if the data is fetched successfully or an error message otherwise.

```dart
body: FutureBuilder<Map<String, double>>(
    future: Provider.of<DataProvider>(context).fetchDataMap(),
    builder: (context, snapshot) {
      if (snapshot.connectionState == ConnectionState.done) {
        if (snapshot.hasError) {
          print(snapshot.error);
          return Center(child: Text('Something went wrong.'));
        }
        return PieChart(
          dataMap: snapshot.data ?? {},
          legendPosition: LegendPosition.top,
        );
      } else {
        return Center(child: CircularProgressIndicator());
      }
    })
```

If you run the app, it should now display the "Something went wrong" error message. If you look at the console, you will see an error like `W/Firestore(32521): (21.3.0) [Firestore]: Listen for Query(data/vztH0rlKnqYCOyzK11HS) failed: Status{code=PERMISSION_DENIED, description=Missing or insufficient permissions., cause=null}`. We will fix it in a bit, for now let's try to open the edit page. You'll see the ugly Flutter exception screen because we don't deal with a lack of data in this page. The simplest way to do that is by updating the body of the scaffold to check whether the cached `dataMap` is `null`:

```dart
body: (dataMap == null)
          ? Center(child: Text('No data to edit'))
          : Padding(
            ...
```

Now that the edit page handles lack of data, we can do even more - restrict access to it altogether if there is nothing to edit. If the `onPressed` callback of an `IconButton` is `null`, the button will appear disabled and will not respond to touch:

```dart
IconButton(
  icon: Icon(Icons.edit),
  onPressed: dataMap == null
      ? null
      : () => Navigator.of(context).pushNamed('/edit'),
)
```

Do keep in mind that users on the web version can still access the edit page by changing the URL, so it's important that we handle the `null` value inside the page as well as restricting access.

#### Check permissions

Now, to fix the `PERMISSION_DENIED` error. We need to allow read/write access to our `data` collection from the Firebase console. Go back to the database and open the *Rules* menu. Here we can define custom security rules which control who can do what in our database. You can find more information about Firebase Security Rules [here](https://firebase.google.com/docs/rules), but for now we will simply allow access to our collection by changing the rules like this:

```
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /data/{data}/{document=**} {
    	allow read, write: if true
    }
  }
}
```

Publish the rules and reload the app. The pie chart should now show, but the edit button will probably still be greyed out - for it to be updated accordingly, you would need to wrap the entire `Scaffold` into a `FutureBuilder` and use the data from the snapshot to verify whether the button should be disabled. You can do that later, for now just restarting the app should do the trick.

If the data fetching is very fast and you'd like to make sure that the loading indicator works as expected, you might need to make the `fetchDataMap` take longer. You can temporarily add something like `await Future.delayed(Duration(seconds: 5))` to make it last 5 seconds longer so you have time to see the progress indicator.

Try to edit the chart while having the document open in the Firebase console. You will see it update immediately! Now whoever uses the app can see and make live updates. If something isn't working correctly, you can check the code [here](https://github.com/acs-upb-mobile/flutter-workshop/tree/firestore) (just remember to use your own configuration and unique `documentID`).

repository: andreeatogoe/flutter-workshop

repo_name: andreeatogoe/flutter-workshop


text:
NSwag.Core [13.12.1](https://www.nuget.org/packages/NSwag.Core/13.12.1)
--------------------

Used by: AspNetCoreNSwag

Target frameworks: net5.0, netcoreapp3.0

License: [MIT](../../../../licenses/mit)

- package license: [MIT](https://licenses.nuget.org/MIT)
- repository license: [MIT](https://github.com/RicoSuter/NSwag.git)
- project license: [Unknown](http://nswag.org/) , License should be verified on http://nswag.org/

Description
-----------
NSwag: The OpenAPI/Swagger API toolchain for .NET and TypeScript

Remarks
-----------
no remarks

Dependencies 2
-----------

|Name|Version|
|----------|:----|
|[NJsonSchema](../../../../packages/nuget.org/njsonschema/10.4.6)|10.4.6|
|[Newtonsoft.Json](../../../../packages/nuget.org/newtonsoft.json/9.0.1)|9.0.1|

*This page was generated by a tool.*


text:
# Training and Test
The library includes scripts to prepare training data and to train both the parse and generate
models.  These scripts are not part of the `pip` install so to use them simply download the
GitHub project and use them in place.  The code for these is located in `scripts/X_yyy`.

# Scripts Directory
```
* 10_Misc                  PlotAMR.py, SpotlightDBServer.sh
* 20_Assemble_LDC2020T02   Collect the LDC training data into test, dev, and train files
* 30_Model_Parse_GSII      Scripts to train the parsing model
* 40_Model_Generate_T5     Scripts to train the generation model
* 50_Build_AMR_View        Script to build and run the GUI
```
Most of the files in these directories start with a number.  To train the model, open the files
in numerical order, check the defined directories, etc.. under the `main` statement and run.
Most of these scripts are simply there to setup parameters and then call the associated library
functions to execute the code.  As such, they are all relatively short and should be fairly
self-explanatory.

## Directory Structure and Run Locations
The scripts in the above directories have a statement at the top `import setup_run_dir`.  This
very simple import causes python to see the script as running from 2 levels up from the current
directory.  This is just a simple way to keep the scripts all in an organized directory and still
have local import of `amrlib` and a common path to `data`.  If you move the script or try to run
it from another location, be sure to remove this import and modify paths accordingly.

All training data, models, etc.. is expected to reside under `amrlib/data`.  When you run the first
script for data prep (`scripts/20_Assemble_LDC2020T02/10_CollateData.py`) the only directory present
should be `amrlib/data/amr_annotation_3.0`.  After running all the scripts in 20_, 30_ and 40_ the
data directory layout will look something like...
```
├── amr_annotation_3.0
├── LDC2020T02
│   ├── dev.txt
│   ├── test.txt
│   └── train.txt
├── model_generate_t5
│   ├── config.json
│   ├── pytorch_model.bin
│   ├── test.txt.generated
│   ├── test.txt.ref_sents
│   └── training_args.bin
├── model_parse_gsii
│   ├── epoch200.pt
│   ├── epoch200.pt.dev_generated
│   ├── epoch200.pt.test_generated
│   ├── epoch200.pt.test_generated.wiki
│   └── vocabs
│       ├── concept_char_vocab
│       ├── concept_vocab
│       ├── lem_char_vocab
│       ├── lem_vocab
│       ├── ner_vocab
│       ├── pos_vocab
│       ├── predictable_concept_vocab
│       ├── rel_vocab
│       ├── tok_vocab
│       └── word_char_vocab
└── tdata_gsii
    ├── dev.txt.features
    ├── dev.txt.features.nowiki
    ├── spotlight_wiki.json
    ├── test.txt.features
    ├── test.txt.features.nowiki
    ├── train.txt.features
    └── train.txt.features.nowiki
```
Note that when downloading models you will get a similar layout but the model directories generally
have a version number appended and a link set, ie.. `model_stog -> model_parse_gsii-v0_1_0`.

## Model Configuration
The `configs` directory has `json` files that contain model parameters used for training.  You will
notice that the train scripts for both models load these.  If you wnat to change the location of
the training data or any other model / training parameters (such as batch size) check in these
files.

## Training data
The latest AMR training corpus, [LDC2020T02](https://catalog.ldc.upenn.edu/LDC2020T02), is available
from the Linguistic Data Consortium.  It is free for institutions that have a membership or $300
for non-members (for non-commercial use).

This newest corpus contains about 60K AMR graphs.
Other versions of LDC data can be used for training and test, however earlier versions are generally
smaller so expect SMATCH and BLEU scores to be slightly lower on the smaller datasets.  The original, freely
available, "Little Prince" corpus is much smaller that the LDC datasets.  It is not big enough to do
a good job of training these large models but it can be used for experimenting; just expect much lower
scores during test.

If you want to try training but don't want to buy the LDC data, it's reasonable to use the pre-trained parser
(or another existing one such as [JAMR](https://github.com/jflanigan/jamr)) to create a synthetic corpus
by parsing a large number of sentences from a free corpus and then using the output AMR graphs as input for training.
This technique has shown to be an effective pre-training method in some papers, however with the larger
LDC2020T02 corpus, pre-training is not generally required.

If you change the name / location of the training files, be sure to update the associated `.json` config
files.


text:
# HelloBotNET

This is a Hello World telegram bot made with NET 6 using a webhook.

## How to Run

If you want to run this bot you need to specify your **bot token**, the **application url** and a **secret token** in the `HelloBotNET.Webhook` project. Optionally, you can specify the **certificate** path to use with your webhook.

Your `secrets.json` or `appsettings.json` should look like the following code:

```JSON
{
  "ApplicationUrl": "https://www.example.com",
  //"Certificate": "/etc/ssl/certs/custom_cert.pem",
  "Telegram": {
    "BotToken": "123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11",
    "WebhookToken": "SUPERSECRETPATH"
  }
}
```

You can also use enviroment variables instead:

| Env                               | Description                                                      |
| :-------------------------------- | :--------------------------------------------------------------- |
| ApplicationUrl                    | Your application url. Ex: <https://example.com>                  |
| Certificate                       | Optional. Certificate Path.                                      |
| Telegram__BotToken                | Your bot token provided by [@BotFather](https://t.me/BotFather). |
| Telegram__WebhookToken            | Your secret token. It must be specified by yourself.             |

Finally, run `HelloBotNET.Webhook` and see the magic.

branch_name: refs/heads/main

gha_language: C#


text:
# OAuth 2 server and client implementation

This project aims to implement the complete
[OAuth 2.0 Authorization Protocol Specification](http://tools.ietf.org/html/draft-ietf-oauth-v2-22).

# Server

The first part is a oauth 2.0 server. It provides the endpoints specified
by oauth 2.0 specification with possibilities to plug code to customize
specific behaviours (see plugins bellow).
You can also extend the server adding additional urls.

Here is an example on how to start the server:

    from oauth2u.server import Server

    server = Server(port=8080)
    server.start()

**Available parameters**

- `port`: specify which port the server will listen (default is 8000)
- `plugins_directories`: a list of absolute directories the server executes to register
   plugins
- `handlers_directories`: a list of absolute directories the server executes to register
   new urls handlers

There is a server on tests/servertest.py.

## Extending the Server

There are two possible ways to extend the server: new urls and plugins

### Plugins

With plugins is possible to customize specific behaviours from the server.
It's similar to a Template Method pattern, but doesn't require you to extend
(or even know) the class that calls it.

You cannot create new plugins, unless you want to call them yourself. But
there are some pre-defined plugins called on specific parts of the server.

To let the server load your plugins automatically you can provide
a list of directories to `Server()` parameter: `plugins_directories`.

##### `authorization_GET`

- __Parameters__
 - `handler`: tornado Request Handler reference

Is called on the Authorization Request handler GET HTTP method, after all
validations are made and the authorization code has already been generated
and saved on database.

If no plugin is registered here the server redirects to `redirect_uri`
without any specific verification.

There is an example usage on how to build a login window using this plugin
and `authorization-POST` on [examples folder](https://github.com/globocom/oauth2u/blob/master/examples/server_with_plugin_to_login.py)

##### `authorization_POST`

- __Parameters__
 - `handler`: tornado Request Handler reference

Is called on the Authorization Request handler POST HTTP method. There is
not default behaviour, if no plugins is registered a `405` status code response is
generated

##### `access_token_response`

- __Parameters__
 - `handler`: tornado Request Handler reference
 - `response`: the default dict to build the json response, with keys: `access_token`,
    `token_type` and `expires_in`

Is called in the end of Access Token request handler, when the json is about to be
written in the HTTP response.
The plugin callback can edit the response dict adding, removing or editing keys.
Just be careful to don't remove [required OAuth 2.0 parameters](http://tools.ietf.org/html/draft-ietf-oauth-v2-22#section-4.1.4)

Example:

        @plugins.access_token_response
        def customize_response(handler, response):
            response.pop('expires_in')   # it's optional, and I don't want it...
            response['user_name'] = 'Bob'

### New urls handlers

Since the server is written using [tornado web framework](http://tornadoweb.org), is
natural that you can register new handlers.

Example:

        import tornado
        from oauth2u.server import handlers

        @handlers.register('/my/custom/url')
        class DummyHandler(tornado.web.RequestHandler):
            def get(self):
                self.write("hello world")

Read the tornado docs for more information on Request Handlers

To let the server load your new url handlers automatically you can provide
a list of directories to `Server()` parameter: `handlers_directories`.

# How to contribute

- Create a fork on github: https://github.com/globocom/oauth2u

- Install the package for development (preferably
  using [virtualenv](http://pypi.python.org/pypi/virtualenv)):

   `$ pip install -e oauth2u`

- Run tests (this command will install test specific dependencies):

   `$ ./runtests`

- Open an [issue](https://github.com/globocom/oauth2u/issues),
  if it doesn't exist yet, assign it to you and commit your changes
  in your fork.

- Send a pull request

- Your commits must have tests, we have 100% coverage, so any code without
  tests is aren't welcome :).
  If your changes modifies API or adds a new feature, you must update the docs too


text:
# **ReadMe Generator**
## License
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
## Description
Read me generator application
## Table Of Contents
1. [ Installation. ](#installation)
2. [ Usage tips. ](#usage)
3. [ License. ](#license)
4. [ Contributing ](#contributing)
5. [ Test ](#test)
6. [ Questions. ](#questions)

## Installation :computer:
**To install necesary dependencies, run the following command:**
```
- npm -i inquirer
```

## Usage :green_book:
You need to run this app in node.js

## License :scroll:
**This project is license under the MIT license**

## Contributing :brain:
Feel free to contribute.

## Test :keyboard:
**To run tests, run the following command:**
```
- npm test
```

### Questions :raising_hand_man:
If you have any questions about the repo, open an issue or contact me  directly at<EMAIL_ADDRESS>You can find more of my work at [GitHub}](https://github.com/benjimosso/).


text:
# Firebase Plugin Vue Demo

> Vue demo app for the NativeScript Firebase plugin

## Usage

``` bash
# Install dependencies
npm install

# Build for production
tns build <platform> --bundle

# Build, watch for changes and debug the application
tns debug <platform> --bundle

# Build, watch for changes and run the application
tns run <platform> --bundle
```

gha_language: TypeScript


text:
# GAUSS-04541 -- GAUSS-04550

GAUSS-04542: "invalid starelkind for pg\_statistic"

SQLSTATE: XX000

Description: Internal system error.

Solution:Contact technical support.

GAUSS-04543: "Failed to find the information of DFS table."

SQLSTATE: 42P17

Description: The HDFS information is not found when you add the delta table distribution information.

Solution: Try again.

GAUSS-04544: "could not obtain lock on partition\(%d\)"

SQLSTATE: 55P03

Description: Internal system error.

Solution:Contact technical support.

GAUSS-04545: "function roach\_handler must return type 'fdw\_handler'"

SQLSTATE: 42809

Description: Internal system error. The  **fdw\_handler**  is not bound when the Roach tool is used to export data.

Solution:Contact technical support.

GAUSS-04546: "could not open roach %s"

SQLSTATE: XX000

Description: The Roach tool cannot be opened after it is exported.

Solution: Check whether the Roach path contained in the location specified by the foreign Roach table can be accessed as expected.

GAUSS-04547: "could not read from roach"

SQLSTATE: XX000

Description: Internal system error. Data cannot be copied using Roach.

Solution:Contact technical support.

GAUSS-04549: "can not specify multiple locations"

SQLSTATE: 0A000

Description: A maximum of one location can be specified in the Roach export method.

Solution: Specify only one location for the Roach foreign table.

GAUSS-04550: "could not close roach %s"

SQLSTATE: XX000

Description: Internal system error. Roach cannot be closed as expected after data is exported.

Solution:Contact technical support.


text:
#### Integrations
##### Microsoft Graph Security
- Deprecated the ***msg-get-user*** and ***msg-get-users*** commands. Use the **Microsoft Graph User** integration for those commands instead.
- Updated the Docker image from `crypto:<IP_ADDRESS>43` to `crypto:<IP_ADDRESS>12`.

repository: demisto/content

gha_language: Python

repo_name: demisto/content


text:
---
layout: recipe
title: Eggnog
from: Joy the Baker
fromurl: http://joythebaker.com/2016/12/homemade-eggnog-with-rum/
prep: 6 hours
cook: 30 minutes
---

#### Ingredients:

* ½ cup whole milk
* ½ cup heavy cream
* 6 egg yolks
* ⅔ cup granulated sugar
* ½-¾ teaspoon freshly grated nutmeg
* 1 cup whole milk
* 1 cup heavy cream
* ½-1 cup spiced rum
* 1 teaspoon pure vanilla extract
* more nutmeg for serving

<br>

#### Directions:

1. In a small bowl combine the ½ cup of whole milk and the ½ cup
of heavy cream. Set aside.
2. In a medium bowl, whisk together egg yolks, sugar, and nutmeg until well combined and thickened slightly.
3. In a medium saucepan, heat remaining milk and cream over medium heat until steaming.
4. While whisking the egg and sugar mixture, slowly drizzle the steaming milk mixture into the egg mixture, tempering the eggs.
5. Whisk until well combined.
6. Add the milky egg mixture back to the saucepan and return to medium-low heat. Stirring often, whisk the mixture until is it slightly thickened and reaches about 175° F. Do not overheat the mixture or it will curdle.
7. Remove from heat and immediately stir in the milk and cream mixture
you set aside earlier. If you'd like, strain through a fine mesh strainer.
8. Stir in ½ to 1 cup of spiced rum and pure vanilla extract.
9. Chill thoroughly (about 6 hours) and serve very chilled with fresh nutmeg sprinkled on top.
10. Eggnog will last up to 5 days in the refrigerator.

repository: lucywyman/recipes

gha_language: HTML

repo_name: lucywyman/recipes


text:
---
title: Agent Configuration Reference
---

This is a reference to all parameters that can be used to configure the rke2 agent. Note that while this is a reference to the command line arguments, the best way to configure RKE2 is using the [configuration file](install_options.md#configuration-file).

### RKE2 Agent CLI Help

> If an option appears in brackets below, for example `[$RKE2_URL]`, it means that the option can be passed in as an environment variable of that name.

```console
NAME:
   rke2 agent - Run node agent

USAGE:
   rke2 agent [OPTIONS]

OPTIONS:
   --config FILE, -c FILE                 (config) Load configuration from FILE (default: "/etc/rancher/rke2/config.yaml") [$RKE2_CONFIG_FILE]
   --debug                                (logging) Turn on debug logs [$RKE2_DEBUG]
   --token value, -t value                (cluster) Token to use for authentication [$RKE2_TOKEN]
   --token-file value                     (cluster) Token file to use for authentication [$RKE2_TOKEN_FILE]
   --server value, -s value               (cluster) Server to connect to [$RKE2_URL]
   --data-dir value, -d value             (data) Folder to hold state (default: "/var/lib/rancher/rke2")
   --node-name value                      (agent/node) Node name [$RKE2_NODE_NAME]
   --node-label value                     (agent/node) Registering and starting kubelet with set of labels
   --node-taint value                     (agent/node) Registering kubelet with set of taints
   --container-runtime-endpoint value     (agent/runtime) Disable embedded containerd and use alternative CRI implementation
   --snapshotter value                    (agent/runtime) Override default containerd snapshotter (default: "overlayfs")
   --private-registry value               (agent/runtime) Private registry configuration file (default: "/etc/rancher/rke2/registries.yaml")
   --node-ip value, -i value              (agent/networking) IPv4/IPv6 addresses to advertise for node
   --node-external-ip value               (agent/networking) IPv4/IPv6 external IP addresses to advertise for node
   --resolv-conf value                    (agent/networking) Kubelet resolv.conf file [$RKE2_RESOLV_CONF]
   --kubelet-arg value                    (agent/flags) Customized flag for kubelet process
   --protect-kernel-defaults              (agent/node) Kernel tuning behavior. If set, error if kernel tunables are different than kubelet defaults.
   --selinux                              (agent/node) Enable SELinux in containerd [$RKE2_SELINUX]
   --lb-server-port value                 (agent/node) Local port for supervisor client load-balancer. If the supervisor and apiserver are not colocated an additional port 1 less than this port will also be used for the apiserver client load-balancer. (default: 6444) [$RKE2_LB_SERVER_PORT]
   --system-default-registry value        (image) Private registry to be used for all system Docker images [$RKE2_SYSTEM_DEFAULT_REGISTRY]
   --kube-apiserver-image value           (image) Override image to use for kube-apiserver [$RKE2_KUBE_APISERVER_IMAGE]
   --kube-controller-manager-image value  (image) Override image to use for kube-controller-manager [$RKE2_KUBE_CONTROLLER_MANAGER_IMAGE]
   --kube-scheduler-image value           (image) Override image to use for kube-scheduler [$RKE2_KUBE_SCHEDULER_IMAGE]
   --pause-image value                    (image) Override image to use for pause [$RKE2_PAUSE_IMAGE]
   --runtime-image value                  (image) Override image to use for runtime binaries (containerd, kubectl, crictl, etc) [$RKE2_RUNTIME_IMAGE]
   --etcd-image value                     (image) Override image to use for etcd [$RKE2_ETCD_IMAGE]
   --kubelet-path value                   (experimental/agent) Override kubelet binary path [$RKE2_KUBELET_PATH]
   --cloud-provider-name value            (cloud provider) Cloud provider name [$RKE2_CLOUD_PROVIDER_NAME]
   --cloud-provider-config value          (cloud provider) Cloud provider configuration file path [$RKE2_CLOUD_PROVIDER_CONFIG]
   --profile value                        (security) Validate system configuration against the selected benchmark (valid items: cis-1.5, cis-1.6 ) [$RKE2_CIS_PROFILE]
   --audit-policy-file value              (security) Path to the file that defines the audit policy configuration [$RKE2_AUDIT_POLICY_FILE]
```


text:
# 9.1.1 Export data as SOAP services

## Business use case narrative

The data services allow you to expose data as a SOAP service. Data services provide a convenient mechanism to configure
a Web service interface for data in various datasources such as relational databases, CSV files, Microsoft Excel sheets,
Google spreadsheets etc.

References:
[Exposing a Datasource as a Data Service](https://docs.wso2.com/display/EI640/Exposing+a+Datasource+as+a+Data+Service)

## Sub-Scenarios

<IP_ADDRESS>. [Expose basic CRUD operations](<IP_ADDRESS>-Expose-basic-CRUD-operations)
<IP_ADDRESS>. [Passing parameter inputs to operation](<IP_ADDRESS>-Passing-parameter-inputs-to-operation)
<IP_ADDRESS>. [Selectively map result data columns to output response](<IP_ADDRESS>-Selectively-map-result-data-columns-to-output-response)
<IP_ADDRESS>. [Validating inputs parameters to the query](<IP_ADDRESS>-Validating-inputs-parameters-to-the-query)
<IP_ADDRESS>. [Inserting multiple records in a single operation](<IP_ADDRESS>-Inserting-multiple-records-in-a-single-operation)
<IP_ADDRESS>. [Nested output read](<IP_ADDRESS>-Nested-output-read)
<IP_ADDRESS>. [Manipulating namespaces](<IP_ADDRESS>-Manipulating-namespaces)
<IP_ADDRESS>. [Control viewing data based on the user role](<IP_ADDRESS>-Control-viewing-data-based-on-the-user-role)
<IP_ADDRESS>. [Invoking multiple operations in a single request](<IP_ADDRESS>-Invoking-multiple-operations-in-a-single-request)
<IP_ADDRESS>. [Invoking multiple operations in a single request](<IP_ADDRESS>-Passing-default-values-for-parameters-where-values-are-not-defined-in-the-request)
<IP_ADDRESS>. [Supporting different data types](<IP_ADDRESS>-Supporting-different-data-types)

gha_language: Java


text:
Authentication Strategies
=========================

Alexandrie supports authenticating using various methods and services.

Here are the details about the various means of authentication you can use in Alexandrie.

> All of these authentication means currently only apply to the frontend.
> The programmatic API for Alexandrie already uses its own token system for authorization.

Local
-----

This strategy is the regular email/password combination flow that is already in place, using the input forms.
This can be disabled, in case you want to exclusively use an alternative authentication strategy, for example.

Configuration:

```toml
# Omitting this entire section from the configuration counts as being disabled.
[frontend.auth.local]
# Whether to enable the use of this strategy.
enabled = true
# Whether to allow the registration of new users using this strategy.
allow_registration = true
```

GitHub
------

This strategy uses OAuth 2 to authenticate the user using its GitHub account.
Filters on who gets authorized can be added based on organization or team membership.

You'll need to create a GitHub OAuth App in order to get the required OAuth client credentials (the replacements for `GITHUB_OAUTH_CLIENT_ID` and `GITHUB_OAUTH_CLIENT_SECRET` in the example below) necessary for Alexandrie to authenticate users.

You can create a new GitHub OAuth App by [**clicking here (for github.com)**](https://github.com/settings/applications/new).
You can also simply find it in your account settings, under `Developer Settings` > `OAuth Apps` and clicking on the `New OAuth App` button.

The homepage URL to use is simply the URL to your Alexandrie instance's homepage.
The authorization callback URL to use is the homepage URL with `/account/github/callback` added.

For example, in the case of the Alexandrie instance hosted at **<https://crates.polomack.eu>**:
- the homepage URL is `https://crates.polomack.eu`.
- the authorization callback URL is `https://crates.polomack.eu/account/github/callback`.

Configuration:

```toml
# Omitting this entire section from the configuration counts as being disabled.
[frontend.auth.github]
# Whether to enable the use of this strategy.
enabled = true
# The client ID of the GitHub OAuth App to use.
client_id = "GITHUB_OAUTH_CLIENT_ID"
# The client secret of the GitHub OAuth App to use.
client_secret = "GITHUB_OAUTH_CLIENT_SECRET"
# The organizations of which membership in one of them is required to be authorized.
# Omit `allowed_organizations` to not require any organization membership.
allowed_organizations = [
    # Being a member of this organization will be sufficient to be authorized.
    { name = "ORG_NAME_1" },
    # But being a member of this one additionally requires membership in one of the specified teams withing that organization.
    { name = "ORG_NAME_2", allowed_teams = ["TEAM_NAME"] },
]
# Whether to allow the registration of new users using this strategy.
allow_registration = true
```

GitLab
------

This uses OAuth 2 to authenticate the user using its GitLab account.
The remote instance can either be the [public one](https://gitlab.com) or a private instance.
Filters on who gets authorized can be added based on group membership.

You'll need to create a GitLab Application in order to get the required OAuth client credentials (the replacements for `GITLAB_OAUTH_CLIENT_ID` and `GITLAB_OAUTH_CLIENT_SECRET` in the example below) necessary for Alexandrie to authenticate users.

You can create a new GitLab Application by [**clicking here (for gitlab.com)**](https://gitlab.com/-/profile/applications).
You can also simply find this page within your account settings, under section `Applications`.

The authorization callback URL to use is the homepage URL with `/account/gitlab/callback` added.

For example, in the case of the Alexandrie instance hosted at **<https://crates.polomack.eu>**:
- the authorization callback URL is `https://crates.polomack.eu/account/gitlab/callback`.

The only OAuth scope needed to be granted for Alexandrie's usage is `read_api`.

Configuration:

```toml
# Omitting this entire section from the configuration counts as being disabled.
[frontend.auth.gitlab]
# Whether to enable the use of this strategy.
enabled = true
origin = "https://gitlab.com"
# The client ID of the GitLab OAuth App to use.
client_id = "GITLAB_OAUTH_CLIENT_ID"
# The client secret of the GitLab OAuth App to use.
client_secret = "GITLAB_OAUTH_CLIENT_SECRET"
# The groups of which membership in one of them is required to be authorized.
# Omit `allowed_groups` to not require any group membership.
allowed_groups = [
    "GROUP_NAME_1",
    # subgroups are specified by their full paths, like this.
    "GROUP_NAME_2/SUBGROUP_NAME_1",
]
# Whether to allow the registration of new users using this strategy.
allow_registration = true
```

repository: Hirevo/alexandrie

gha_language: Rust

repo_name: Hirevo/alexandrie


text:
# EchoRegions

EchoRegions is a tool used for parsing and utilizing region files created in EchoView.

EchoRegions is designed with [Echopype](https://github.com/OSOceanAcoustics/echopype) in mind, and parsed region files will be able to mask or be overlaid on top of Echopype echograms. However, the EVR, EVL, and ECS parsers do not require Echopype to be installed.

## Functionality and Usage

Please see the [API documentation](https://echoregions.readthedocs.io/en/latest/api.html) for all of the classes and functions availible in echoregions.

Or, you can jump right in using the provided [example notebook](https://github.com/ngkavin/echoregions/blob/main/notebooks/plotting_example.ipynb)!

repository: ngkavin/echoregions

repo_name: ngkavin/echoregions