text:
# trelliswifi
#### ESP32 based project for multi-purpose buttons and colors using NeoTrellis

## Goals

- Leverage the Adafruit NeoTrellis + ESP platform to generate events via Wifi
  - Publish button press events via MQTT (long and short combos using bitmask values)
  - Use MQTT subscriptions to provide complete control of lights and animations
- Keep config in non-volatile ram (one unchanged code image for multiple devices)

## Background

I needed a multi-purpose control panel of buttons to turn on/off lights in the
house. I also thought it would be nice if it had lights to provide
feedback on what is currently on. That idea evolved to using this cool gizmo as a
portable remote that interfaces with my home server via MQTT through Wifi.
Built-in animations are implemented to allow LEDs under buttons to blink, pulse or
change colors. At this point, it is generic enough to be used as a frontend for
controlling anything while providing 64 RGBs as a feedback display. :sparkles:

[![Watch the video](https://img.youtube.com/vi/qqpkBH1jO0A/default.jpg)](https://youtu.be/qqpkBH1jO0A)

## Hardware

This project is written for an 8x8 NeoTrellis setup with a Huzzah ESP32 feather. The non-volatile storage part of this project leverages the ESP32's
[preferences library](https://github.com/espressif/arduino-esp32/blob/master/libraries/Preferences/src/Preferences.h).

**All parts can be purchased at [my favorite DIY store (aka Adafruit)](https://adafruit.com)**:

- Adafruit [HUZZAH ESP32](https://www.adafruit.com/product/3405)
- Adafruit [8x8 Trellis Feather M4 Acrylic Enclosure + Hardware Kit](https://www.adafruit.com/product/4372)
- 4 x [Adafruit NeoTrellis RGB Driver PCB for 4x4 Keypad](https://www.adafruit.com/product/3954)
- 4 x [Silicone Elastomer 4x4 Button Keypad - for 3mm LEDs](https://www.adafruit.com/product/1611)
- [Lithium-Ion Polymer Battery](https://www.adafruit.com/product/1578)
- [Toggle Switch](https://www.adafruit.com/product/3220)

:paperclip:
These pages from [learn.adafruit.com](https://learn.adafruit.com) tell you how to put it all together:
- [NeoTrellis Feather Case Assembly](https://learn.adafruit.com/neotrellis-feather-case-assembly)
- [Adafruit NeoTrellis](https://learn.adafruit.com/adafruit-neotrellis/)

:warning:
The 8x8 setup is comprised of four 4x4 [keypads](https://www.adafruit.com/product/3954) and each
of them must have a unique I2C address. Make sure to address them properly by
leaving one untouched, bridging "A0" on the second, "A1" on the third, and both "A0+A1" on the fourth. If
you use a different configuration, tweak
[the code here](https://github.com/flavio-fernandes/trelliswifi/blob/f9d5205d429969cbee1299608cc529e23655c9d0/src/lights.cpp#L19-L22) before uploading the project to your ESP32 board.

## Software

### Pre-requisites

- [platformio.org](https://platformio.org/) environment (see [platformio-ide](https://platformio.org/platformio-ide)) with [vscode](https://docs.platformio.org/en/latest/integration/ide/vscode.html)
- WIFI and an MQTT server

If you do not want to set an MQTT server up, consider [using a public](https://github.com/mqtt/mqtt.github.io/wiki/public_brokers) one, like [Adafruit.IO](https://io.adafruit.com/)

### Configuration

After cloning this repo, there are 2 files that you will need to modify before being able to
compile and upload the code:

#### (1) **platformio.ini**

Rename _[platformio.ini.sample](https://github.com/flavio-fernandes/trelliswifi/blob/master/platformio.ini.sample)_ to _platformio.ini_ and change any settings you would like.

#### (2) **include/netConfig.h**

Rename _[netConfig.h.sample](https://github.com/flavio-fernandes/trelliswifi/blob/master/include/netConfig.h.sample)_ to _netConfig.h_ . Note that for using OTA, the settings here must match what you configured in _platformio.ini_

#### :checkered_flag: Compile and Upload

:construction: At the time of this writing, there is [a bug](https://github.com/adafruit/Adafruit_BusIO/issues/69) in [Adafruit_BusIO](https://github.com/adafruit/Adafruit_BusIO) library that will make compilation fail as follows:

```
.pio/libdeps/esp32dev/Adafruit<EMAIL_ADDRESS>In member function 'void Adafruit_I2CDevice::end()':
.pio/libdeps/esp32dev/Adafruit BusIO@src-de43b9da31d281331630329764ceaa16/Adafruit_I2CDevice.cpp:44:10: error: 'class TwoWire' has no member named 'end'
   _wire->end();
```

The fix has already [been merged](https://github.com/adafruit/Adafruit_BusIO/pull/70), but if you need to work around it, simply make the changes locally to match what is done in that PR. :sweat_smile:

### Initial configuration of MQTT and topic

It is time to jump into the temporary webserver started by your ESP, so you can provide details on the
Wifi and MQTT server it should connect to every time it boots. This is likely something you will just do
once per device since the config is kept in non-volatile memory.

#### Connect to ESP's temporary AP

When booted for the first time -- or when you force the device to do so
([section below](https://github.com/flavio-fernandes/trelliswifi#recycle-resettingchanging-values-in-non-volatile-memory))
-- the ESP will boot as an
access point and start to broadcast its own SSID. I can't tell you what that SSID will be because each ESP
comes with a unique MAC address. Simply look for SSIDs that start with the name **ESP32_**.

Once a Wifi connection is established, you should be presented with the WiFiManager window. If that is not the
case, open your browser and connect to the [portal URL](http://<IP_ADDRESS>/):

**http://<IP_ADDRESS>/**

A couple of caveats you should keep in mind while configuring your device:

- Use a unique topic prefix and do not forget the value you used. It should end with the **/** character, as
shown below. The default value used for this field is **/trelliswifi/**
- The MQTT server is mandatory. It can be an IP address or a [FQDN](https://kb.iu.edu/d/aiuv) (like io.adafruit.com).
- MQTT username and password fields are optional, depending on the server you use.

![WiFi Manager Example](https://i.imgur.com/A90sNwd.png)

### :recycle: Resetting/changing values in non-volatile memory

Let's say you need to change the non-volatile setting or would like to wipe the existing values. No problem! :relaxed:

In [less than 2 minutes](https://github.com/flavio-fernandes/trelliswifi/blob/f9d5205d429969cbee1299608cc529e23655c9d0/src/net.cpp#L545-L553)
after turning the device on, do a "long press" on the 4 corner buttons. Long press means pressing
down the button until it turns solid purple.

![Factory Reset Mode](https://i.imgur.com/vG5BZrs.jpg)

This will make the trelliswifi clear all settings and restart its internal web server, as explained
[above](https://github.com/flavio-fernandes/trelliswifi#initial-configuration-of-mqtt-and-topic).
Clean, rinse and repeat. :bowtie:

## Animate via built-in button pushes

Before interacting with the device via network messages, try holding down button 8 until it turns purple and release it.
As a point of reference, that is one of the 4 corner buttons. Which corner depends on the IC2 addresses used. If it all goes well, all LEDs should turn on white. Short pressing the same button (a second or two)
should undo that behavior.

Next, try long-pressing buttons 8 and 16. Short pressing them should make the animation stop.
For all the built-in animations, look at the [localButtonProcess function](https://github.com/flavio-fernandes/trelliswifi/blob/f9d5205d429969cbee1299608cc529e23655c9d0/src/animations.cpp#L18-L35).
You will see pairs of 64 bitmasks for each animation. The first pair value represents the
buttons that need to be short pressed and the second bitmask is for the buttons that have to be held down until they
turn purple (aka long press).

## Let's talk MQTT

### Receiving events

Once trelliswifi is able to establish a connection with the configured MQTT server, there
are all sorts of fun you can have with it. The device will publish into 5 different MQTT topics
to provide updates on its current state. First, it may be better to explain how to get them, and then
we can dive into each one of these topics.

#### Install MQTT client so you can interact with trelliswifi

Any MQTT client will work. The one I use quite often and really like is called Mosquitto.
More info at [mosquitto.org/download/](https://mosquitto.org/download/).
Here is a cheat sheet set of commands for easily getting it on your computer:

```bash
$ # If you are using Debian / Ubuntu / Raspberry-Pi:
$ sudo apt-add-repository ppa:mosquitto-dev/mosquitto-ppa
$ sudo apt-get update
$ sudo apt-get install -y mosquitto-clients

$ # If you are using a mac:
$ brew install mosquitto
```

#### :star2: Doing MQTT via a browser

If you have a chrome browser and would like to use that instead of Mosquitto, check out
[MQTTLens](https://docs.litmusautomation.com/display/DOC/MQTTLens). I found it super easy
to install and use. Kudos to [Sandro](https://github.com/sandro-k) for building such an
awesome [javascript-based app](https://github.com/sandro-k/MQTTLensChromeApp).

#### Start (or use an existing) MQTT server

Start an MQTT server or connect to an existing one. For simple testing,
you can just use a known public server, like [io.adafruit.com](https://io.adafruit.com/),
[test.mosquitto.org](https://test.mosquitto.org/) or anything listed
in [mqtt.github.io](https://github.com/mqtt/mqtt.github.io/wiki/public_brokers).

:exclamation: It is important that you have the same **MQTT server** value
[configured](https://github.com/flavio-fernandes/trelliswifi#connect-to-esps-temporary-ap)
for the trelliswifi device you use. The same goes for the **MQTT topic prefix** attribute.

 That will trigger the device to publish a "_buttons_" event.
Do you see it? Without closing the _mosquitto_sub_ command, open a new session, and let's poke the device to
generate the other 4 topics:

```bash
MQTT=test.mosquitto.org  ; # replace this with whatever you decide to use as MQTT server
PREFIX_CONFIGURED=trelliswifi ; # replace this value with whatever you configured in the web portal

mosquitto_pub -h $MQTT -t "/${PREFIX_CONFIGURED}/ping" -n
```

Here is a sample output:
```text
2020-02-22T20:06:03-0500 : 0 : /trelliswifi/buttons : {"p":"0x0000000000000001","l":"0x0000000000000000","x":"0x0000000000000000"}

2020-02-22T20:06:06-0500 : 0 : /trelliswifi/battery : {"volts":"3.70","isLow":"no"}
2020-02-22T20:06:06-0500 : 0 : /trelliswifi/uptime : {"up":"14","mqttUp":"14","dog":"14"}
2020-02-22T20:06:06-0500 : 0 : /trelliswifi/memory : {"maxMsg":"105","freeKb":"246","minFreeKb":"244","maxAllocKb":"111"}
2020-02-22T20:06:06-0500 : 0 : /trelliswifi/etc : {"pixelsOn":"0x0000000000000000","lightUnitsSize":"0","watchDog":"no"}
```

More info on each one of the topics you are seeing:

- /${PREFIX_CONFIGURED}/**buttons**
  - Gives you 3 hexadecimal values [that represent](https://github.com/flavio-fernandes/trelliswifi/blob/f9d5205d429969cbee1299608cc529e23655c9d0/src/buttons.cpp#L6-L8):
    - (p) buttons that were pressed and released between 200 milliseconds and 2.4 seconds
    - (l) buttons that were pressed and held for longer than 2.4 seconds
    - (x) buttons held down for longer than 15 seconds
- /${PREFIX_CONFIGURED}/**battery**
  - Tells you the current battery voltage
  - Gives an "isLow" boolean, which gets set as _true_ when [battery output is less than 3.45 volts](https://github.com/flavio-fernandes/trelliswifi/blob/f9d5205d429969cbee1299608cc529e23655c9d0/src/main.cpp#L79-L88)
- /${PREFIX_CONFIGURED}/**memory**
  - Basic runtime info on [memory usage](https://github.com/flavio-fernandes/trelliswifi/blob/f9d5205d429969cbee1299608cc529e23655c9d0/src/net.cpp#L493-L499) of ESP
- /${PREFIX_CONFIGURED}/**uptime**
  - Gives you info on how long trelliswifi has been operational
    - **up**: minutes since it was turned on
    - **mqttUp**: minutes since last time it connected to MQTT server
    - **dog**: increases every minute, and gets reset when a specific MQTT request is received:
      - mosquitto_pub -h $MQTT -t "/${PREFIX_CONFIGURED}/ping" -m periodic
      - For more info on how that is used, see [this code](https://github.com/flavio-fernandes/trelliswifi/blob/f9d5205d429969cbee1299608cc529e23655c9d0/src/net.cpp#L386-L387) and check the box that says 'needs periodic pings' in the web portal.
- /${PREFIX_CONFIGURED}/**etc**
  - Gives a bitmask in hexadecimal, representing which LEDs are currently on
  - The current 'needs periodic pings' configuration is available via the 'watchDog' attribute here.
  - It also tells how many _light unit entries_ are in use. More on that [later on](https://github.com/flavio-fernandes/trelliswifi#light-unit-entries), but these are created/deleted via the set/rm commands.

### Publishing events

The trelliswifi device subscribes to **ping** and **cmd** topics in order to handle external requests.

At this point, there is not much more to say about the _ping_ topic. It is simply a way of prompting
for status as well as resetting the watchdog. These status topics are
[generated every 10 minutes](https://github.com/flavio-fernandes/trelliswifi/blob/f9d5205d429969cbee1299608cc529e23655c9d0/src/net.cpp#L401-L410),
regardless of the _ping_ message.

#### The /${PREFIX_CONFIGURED}/**cmd** topic

- cmd
  - op
    - $ANIMATION_NAME
    - rm
    - set

#### Animations

These are actually built-in entries that use [id](https://github.com/flavio-fernandes/trelliswifi/blob/f9d5205d429969cbee1299608cc529e23655c9d0/src/animations.cpp#L10) [511](https://github.com/flavio-fernandes/trelliswifi/blob/f9d5205d429969cbee1299608cc529e23655c9d0/src/lightUnit.h#L11). There is nothing special about that id; it's just a number.

The name simply maps to a pre-built function. See [initCmdOpHandlers](https://github.com/flavio-fernandes/trelliswifi/blob/f9d5205d429969cbee1299608cc529e23655c9d0/src/msgHandler.cpp#L181-L204)
if you are interested in learning how that was coded.

Give them a spin, using these example commands:

```bash
TOPIC="/${PREFIX_CONFIGURED}/cmd"

mosquitto_pub -h $MQTT -t $TOPIC -m '{"op" : "flash"}'
mosquitto_pub -h $MQTT -t $TOPIC -m '{"op" : "flashlight"}'
mosquitto_pub -h $MQTT -t $TOPIC -m '{"op" : "!flashlight"}'
mosquitto_pub -h $MQTT -t $TOPIC -m '{"op" : "counter6"}'
mosquitto_pub -h $MQTT -t $TOPIC -m '{"op" : "!counter"}'
mosquitto_pub -h $MQTT -t $TOPIC -m '{"op" : "crazy"}'
mosquitto_pub -h $MQTT -t $TOPIC -m '{"op" : "scan"}'

# stop animation using the well known id
mosquitto_pub -h $MQTT -t $TOPIC -m '{"op" : "rm", "id": "511"}'
```

#### Light Unit Entries

At the heart of the display implementation, the trelliswifi code handles
[entries](https://github.com/flavio-fernandes/trelliswifi/blob/f9d5205d429969cbee1299608cc529e23655c9d0/src/lightUnit.cpp#L7-L8)
called [LightUnit](https://github.com/flavio-fernandes/trelliswifi/blob/f9d5205d429969cbee1299608cc529e23655c9d0/src/lightUnit.h#L40-L50).
That is implemented using the [C++ STL map](http://www.cplusplus.com/reference/map/map/).

You can get a good feel for all the attributes you can associate with an entry by looking at
the [file lightUnit.h](https://github.com/flavio-fernandes/trelliswifi/blob/master/src/lightUnit.h).

```c++
typedef struct LightUnit_t {
  LightUnitId id;
  uint64_t pixelMask;  // overriden by randomPixels
  uint32_t color;  // overriden by sameRandomColor
  int8_t brightness;  // overriden by pulse. Adjusts color (0->ignored, 1->dark full->255)
  LightUnitAnimation animation;
} LightUnit;

typedef struct LightUnitAnimation_t {
  uint32_t frames;      // total number of frames this is part of
  uint32_t step;        // the frame index for this
  uint32_t speed;       // overriden by pulse. how many refreshes between each frame (in 100 ms units)
  uint64_t expiration;  // how many steps until animation stops (0 => never)
  LightUnitId dependsOn;   // will expire if entry it depends on is gone (0 => no-dep)
  bool randomPixels;       // pick a random pixelMask
  bool sameRandomColor;    // overriden by randomColor. Pick a random color for pixelMask
  bool randomColor;        // overriden by rainbowColor. Pick a random color for each pixel in mask
  bool rainbowColor;       // pick rainbow color for pixelMask (or pixel, when used with randomColor)
  bool keepPixelWhenDone;  // upon expiration, leave pixelMask alone?
  bool blink;              // set color to 0 on every other frame
  bool pulse;              // overriden by rainbowColor, randomColor, sameRandomColor.
                           // if true, will apply modify brightness to color
} LightUnitAnimation;
```

In order to be super flexible on what and how to display things, the **cmd** uses JSON strings.
The [MQTT library limits](https://github.com/adafruit/Adafruit_MQTT_Library/blob/223d419ebdff8f594da6132755628b12ecbbf7d7/Adafruit_MQTT.h#L110)
how long these strings can be, but nothing stops you from tweaking that! The ESP32 can totally handle more
than 150 bytes, but many original Arduino boards don't have much memory.
**set cmd** takes an optional **id**, which allows us to break the attributes of a given
entry into multiple messages. If **id** is not provided in a **set** command, the implementation
creates a new entry. Let's clarify that with examples.

Creating entries that use multiple pixels.
```bash
# pixels: all 64
# id: not provided, so a new entry will be created
# color: lightest green
mosquitto_pub -h $MQTT -t $TOPIC -m '{"op" : "set", "pixelMask": [4294967295,<PHONE_NUMBER>], "color": 4096}'

# remove all entries
mosquitto_pub -h $MQTT -t $TOPIC -m '{"op" : "rm"}'

# pixels: higher 32
# id: 10
# color: brightest blue
mosquitto_pub -h $MQTT -t $TOPIC -m '{"op" : "set", "id": 10, "pixelMask": [0,<PHONE_NUMBER>], "color": 255}'

# pixels: lower 32
# id: 11
# color: brightest green
mosquitto_pub -h $MQTT -t $TOPIC -m '{"op" : "set", "id": 11, "pixelMask":<PHONE_NUMBER>, "color": 65280}'

# pixels: 32 in the middle, covering 16 pixels from ids 10 and 11 because its id is lower (lowest gets drawn last)
# id: 9
# color: brightest red
mosquitto_pub -h $MQTT -t $TOPIC -m '{"op" : "set", "id": 9, "pixelMask": {"low":<PHONE_NUMBER>, "high": 65535}}'
mosquitto_pub -h $MQTT -t $TOPIC -m '{"op" : "set", "id": 9, "color": 16711680}'

# remove ids 9,10,11
for i in {9..11}; do mosquitto_pub -h $MQTT -t $TOPIC -m "{'op' : 'rm', 'id': $i}" ; done

# Add random blinking pixels of random colors that self delete in 10 seconds
mosquitto_pub -h $MQTT -t $TOPIC -m '{"op" : "set", "animation": {"expiration":100, "randomPixels":1, "randomColor":1, "blink":1}}'
```

#### A word on **pixelMask** attribute

:boom:
As you may have noticed, **pixelMask** is a bitmask that
[can represent all 64 LEDs](https://github.com/flavio-fernandes/trelliswifi/blob/f9d5205d429969cbee1299608cc529e23655c9d0/src/msgHandler.cpp#L54-L80)
in the device. Unfortunately, a single integer value can only hold up to 40 bits in ArduinoJson library (0x8000000000).
There are 3 workarounds for dealing with this limitation:
1) shift: If you need to reach beyond bit 40, use "pixelMask" with a single integer and then "pixelShiftUp". Examples below use that
approach.
2) array: As you can see in the example above, "pixelMask" can be an array of 2 elements that represent low and high 32 bits.
3) object: "pixelMask" can also be a JSON object that explicitly dictates low and high attributes.

Time for more examples! Making 3 entries that run on the same number of frames and speed to produce a simple color animation:
```bash
for i in {10..12}; do \
  mosquitto_pub -h $MQTT -t $TOPIC -m "{'op' : 'set', 'id': $i, 'pixelMask': 1, 'animation': {'speed': '10'}}"
  mosquitto_pub -h $MQTT -t $TOPIC -m "{'op' : 'set', 'id': $i, 'animation': {'frames': '3'}}"
done
mosquitto_pub -h $MQTT -t $TOPIC -m '{"op" : "set", "id": 10, "color": 16711680, "animation": {"step": "0"}}'
mosquitto_pub -h $MQTT -t $TOPIC -m '{"op" : "set", "id": 11, "color": 65280, "animation":    {"step": "1"}}'
mosquitto_pub -h $MQTT -t $TOPIC -m '{"op" : "set", "id": 12, "color": 255, "animation":      {"step": "2"}}'

# Introducing entries dependence
for i in {10..11}; do \
  mosquitto_pub -h $MQTT -t $TOPIC -m "{'op' : 'set', 'id': $i, 'animation': {'dependsOn': $((i+1))}}"
done

# Removing entry 12 causes its 'dependents' to also get deleted
mosquitto_pub -h $MQTT -t $TOPIC -m "{'op' : 'rm', 'id': 12}"
```

For the last batch of examples, let's create some blinking and pulsing LEDs:
```bash
# Create entry with 4 green pixels
mosquitto_pub -h $MQTT -t $TOPIC -m '{"op" : "set", "id": "1", "pixelMask": "15", "color": "65280"}'

# Shift the pixels up 3 positions
mosquitto_pub -h $MQTT -t $TOPIC -m '{"op" : "set", "id": "1", "pixelShiftUp": 3}'

# Shift the pixels down 1 position
mosquitto_pub -h $MQTT -t $TOPIC -m '{"op" : "set", "id": "1", "pixelShiftDown": 1}'

# Make it blink
mosquitto_pub -h $MQTT -t $TOPIC -m '{"op" : "set", "id": "1", "animation": {"blink": 1}}'

# Make it pulse
mosquitto_pub -h $MQTT -t $TOPIC -m '{"op" : "set", "id": "1", "animation": {"blink": 0, "pulse": 1}}'

# Make it rainbow colors
mosquitto_pub -h $MQTT -t $TOPIC -m '{"op" : "set", "id": "1", "animation": {"rainbowColor": 1}}'

# Add a blinking red button 1
mosquitto_pub -h $MQTT -t $TOPIC -m '{"op" : "set", "id": "123", "pixelMask": 1, "color": 16711680}'
mosquitto_pub -h $MQTT -t $TOPIC -m '{"op" : "set", "id": "123", "animation": {"blink": 1}}'
# Reduce its brightness
mosquitto_pub -h $MQTT -t $TOPIC -m '{"op" : "set", "id": "123", "brightness": 9}'
# Move it to last button
mosquitto_pub -h $MQTT -t $TOPIC -m '{"op" : "set", "id": "123", "pixelShiftUp": 63}'

# remove all entries
mosquitto_pub -h $MQTT -t $TOPIC -m '{"op" : "rm"}'
```

### Closing thoughts

I hope you have as much fun with trelliswifi as I do. If you hit a snag on anything mentioned here, please do not
hesitate to open an issue or make a PR. More importantly, I'm super curious to learn more about how this platform
can be leveraged to do the amazing IoT things you do. Enjoy!  :revolving_hearts:

### TO DO :construction:

- Make I2C address used for Trellis keypad configurable and stored in non-volatile memory (via WIFI Manager)
- Add buzzer for sounds :musical_score:
- Adapt for Trellis of different sizes
- Document how this gizmo is used together with [github.com/flavio-fernandes/mqtt2cmd](https://github.com/flavio-fernandes/mqtt2cmd/blob/ad14873e051e48ba01b3c93434e8daf32e608004/data/config.yaml.flaviof#L21)

repository: flavio-fernandes/trelliswifi

repo_name: flavio-fernandes/trelliswifi


text:
# Perun RPC (server) #

This module wraps others into a single web application and represents single Perun instance. Application contains server side RPC API which you can use to manage your Perun instance. For this purpose, Perl CLI tools are also provided in *perun-cli*. See on bottom how to make it work. GUI is provided by *perun-web-gui* module, which is not packaged inside *perun-rpc* and must be built and deployed separately into some web server (Apache).

Application is expected to run inside Tomcat 7 container and receive all requests on AJP port (8009). Perun rely on Apache web server for passing requests, authentication of users and setting up environment variables. User credentials are passed to Perun to perform authorization. If approved, required action is performed and response returned to user through Apache web server.

You can find full documentation of Perun RPC API [on our web](https://perun-aai.org/documentation/technical-documentation/rpc-api/index.html).

### Build and local run ###

> Please note, that to actually run Perun, you must:
>
> * Setup DB and create initial user entry including roles and authz data.
> * Have a bunch of configuration files with proper settings in /etc/perun/ folder
> * Setup some authentication in Apache.
> * Pass requests and authentication data from Apache to Tomcat (AJP port) so Perun can locate user based on that.
>
> For now NON of these steps are covered on public wiki/web.
>
> **You can use [Perun ansible](https://github.com/CESNET/perun-ansible) scripts to install instance of Perun with default configuration and initial user with basic auth.**

To build production version of Perun RPC from sources use Maven command in a project root folder:

```
mvn clean install -pl perun-rpc -am -Dproduction -DskipTests
```

You can then deploy ``perun-rpc/target/perun-rpc.war`` into running Tomcat and it will be running under *http(s)://localhost:8009/perun-rpc* path.

You must setup Apache to provide authentication or modify it to provide necessary data in HTTP headers. Otherwise all requests to the app will end with wrong authentication.

Also you must redirect all requests to the right URL (provided by tomcat), since GUI and CLI tools expect to find Perun on *http(s)://[hostname]/[krb/cert/fed/oauth]/rpc/[rest_of_request_path+params]* URL.

You can also run Perun locally (e.g. for some tests). Just run Maven with tomcat plugin in ``perun-rpc/`` folder:

```
# in memory version
mvn tomcat7:run-war

# against real DB with config in /etc/perun/
mvn tomcat7:run-war -Ddevel
```

### CLI tools ###

Perun can be managed using CLI tools (Perl scripts). You can find them in *perun-cli* module.

In order to use them, you must install following Perl packages (example for Debian):

```bash
apt-get install libswitch-perl liblwp-authen-negotiate-perl libjson-any-perl libtext-asciitable-perl libterm-readkey-perl libwww-perl libcrypt-ssleay-perl libtext-unidecode-perl libdate-calc-perl libnet-ldap-perl libjson-perl libyaml-perl qrencode
```

Setup path for Perl to locate Perun modules:
```
export PERL5LIB="[folder_with_cli_tools]"
```

And choose authentication method to follow the next steps:

#### Kerberos, certificate or IdP federation ####
Setup environment variables to locate your Perun instance:

* URL to your Perun instance, pick krb for Kerberos authz, cert for certificate and fed for IDP federation (it depends on your Apache setup):
    ```
    export PERUN_URL="https://[instance_url]/[krb/cert/fed]/rpc/"
    ```
* Your login and password:
    ```
    export PERUN_USER="[login]/[password]"
    ```

* Keep the type empty or setup to match REALM returned by Apache (e.g. for Kerberos):
    ```
    export PERUN_RPC_TYPE="Perun RPC"
    ```

#### OIDC ####
* Install Python 3
* Install its keyring library:
    ```
    pip install keyring
    ```
* Enable OIDC:
    ```
    export PERUN_OIDC=1
    ```
* Specify which configuration from the configuration file should be used:
    ```
    export PERUN_OIDC_CONFIG="[configuration_name]"
    ```
* Specify endpoints in the configuration file `perun-cli/Perun/auth/oidc_config.yml`
* In order for QR code authentication to work, make sure qrencode is installed:
    ```
    sudo apt install qrencode
    ```

* > Note that:
  >
  > * Endpoints are described in a sample file `perun-cli/Perun/auth/sample_oidc_config.yml`
  > * Tokens can be revoked by calling `./revokeOidcToken` script
  > * For bash mode it is recommended to perform the authentication beforehand by calling `./oidcAuthentication` script

You can then test connection by listing VOs like: ``./listOfVos``

repository: CESNET/perun

branch_name: refs/heads/master

extension: md

gha_language: Java

license_type: permissive

repo_name: CESNET/perun


text:
# Lab7-BST

## Purpose
To learn how to add and remove from a binary search tree. This lab will prepare you for the upcoming AVL lab.

## WARNING
You will build off of your code in this lab for the next (AVL) lab.  If you want to have a miserable time finishing the AVL lab, use code that you don't understand for this lab.  In other words, don't use any code you don't understand.

## Background
A binary search tree (BST), which may sometimes be called an ordered or sorted binary tree, is a node-based data structure where each node references a value, a left child, and a right child. Binary search trees are characterized by the following properties:

* The left subtree of a node contains only nodes with values less than the node's value.
* The right subtree of a node contains only nodes with values greater than the node's value.
* There must be no duplicate nodes.
* Both the left and right subtrees of a node also must be binary search trees (each subtree must have the first three properties). [Wikipedia](https://en.wikipedia.org/wiki/Binary_search_tree)

## Requirements
You will need these files to complete this assignment: BST.zip  Download

### Part 1 - Add Nodes to the Tree (13 points)
* Implement the NodeInterface getRootNode() function and the add() function.
* You must use your implementation of NodeInterface properly in the structure of your binary search tree.

### Part 2 - Remove and Clear (26 points)
* Implement the remove() and clear() methods from the BSTInterface.
* There are several logically correct ways to remove from a binary search tree. See the requirement notes for instructions on how to remove correctly to pass the test driver.

### Part 3 - More intricate adds and removes (13 points)
* This will more thoroughly test your add and remove() functions.

### Part 4 - Border cases and step-by-step removal (13 points)
* Make sure that your tree doesn't accept duplicates, successfully handles invalid remove requests, etc.

### Part 5 - Full step-by-step removal from a tree (13 points)
* Adds all the integers 0-20 to your tree then removes them one at a time until the tree is empty.

### Part 6 - Valgrind  (22 points Pass/Fail)
*Note: This is worth more because it will help you in the AVL lab.*
* Run and pass Valgrind on your program to ensure that you have no memory leaks.
* You must pass parts 1 - 5 as well as Valgrind to receive credit for this part.

### Requirement Notes
* There are multiple correct methods for removing nodes from a tree; each method may result in a distinct tree. Some conventions need to be used to ensure that your tree properly matches ours. When removing a node with only one child, replace that node with its child and use the in-order predecessor when removing nodes with two children).
* Remember to disallow duplicate entries and to handle the case when the element to be removed is not in the tree.
You are required to write a separate '.h' and '.cpp' for every class you implement.
You may not use any standard library data structures for this lab (vector, list, etc.).
There are many correct ways to implement node objects for linked structures. These include but are not limited to: friend classes, internal classes, and non-internal/non-friend class with various getter and setter functions.  Since this lab is most easily completed when passing node pointers by reference, it is essential that we have direct access to the left and right pointers of the node objects.
* Simple getters of the return type `Node*`, create copies and are incompatible with functions which expect `Node*&`. Therefore the functions used by the test driver `getRightChild()` and `getLeftChild()` will not suit our needs. Any of the three strategies listed below will be sufficient.
* Friend Classes: the Node Class will list the BST class as its friend, not the other way around. This allows private data members to be visible to listed friends.
* Inner (Nested) Classes/Structs: almost identical to the convention we used in the LinkedList lab, but include the inheritance statement to the NodeInterface.  If the inner class is declared private, its public data members will not exceed the scope of the containing class.
* Non-Friend, Non-Inner classes: in this case, you can write extra getter and setter functions (along side the test driver required getters), with the return type of `Node*&`, which will be compatible with functions requiring `Node*&`. This way you can protect your private data members while still using reference parameters.

license: MIT

repository: landiinii/C-Based

branch_name: refs/heads/main

repo_name: landiinii/C-Based


text:
+++
# About/Biography widget.
widget = "about"
active = true
date = "2016-04-20T00:00:00"

# Order that this section will appear in.
weight = 69

# List your academic interests.
[interests]
  interests = [
    "Aerosol particles",
    "Air quality",
    "Climate change"
  ]

# List your qualifications (such as academic degrees).
[[education.courses]]
  course = "PhD in Chemistry"
  institution = "Johnannes Gutenberg University, Mainz - Max Planck International Research School"
  year = 2018

[[education.courses]]
  course = "MSc in Chemistry"
  institution = "Instituto Venezolano de Investigaciones Científicas"
  year = 2013

[[education.courses]]
  course = "BSc in Chemistry"
  institution = "Universidad Simón Bolívar"
  year = 2007

+++

# Biography

I am doing research on atmospheric aerosols and their climate and environmental impact. I have been involved in air quality and climate change projects in Venezuela, Brazil and Germany. Specifically, I have experience in using optical instrumentation for aerosol measurements.

This website comprises a compilation of my academic publications and some resources for science communication that I will be sharing in the blog section (mostly in Spanish). Moreover, I will be posting notes about data analysis and visualization, especially of environmental data.

[![ko-fi](https://www.ko-fi.com/img/donate_sm.png)](https://ko-fi.com/Y8Y6J1UL)

repository: jorgesat/kn-website

repo_name: jorgesat/kn-website


text:
# Bin Temperature Sensor
This project is a gadget to monitor the temperature in a grain bin. This is important because when grain heats it can spoil and a farmer can lose lots of money. The current iteration is the cheapest when 4 bins are wired up and costs about $140 per bin. That cost can be contrasted with the current bin monitoring systems which can cost up to $5000 a bin. The next iteration will focus on lowering the per bin cost for when more than 4 bins are wired up, and the iteration after that will integrate Arduino Cloud into the project, so that all collected data can be stored for later use.

## Main Hardware
### Arduino MKR 1400
This will be the Arduino that will send the alerts to the farmer and possibly one day send data to the Arduino Cloud. At the moment the code is designed to be controlled soley by the MKR 1400, but in the next iteration it will recieve alerts from regular Arduinos.

### Temperature Sensor
The DHT 22 or the DFR0198 sensor is currently being used as the sensor. Three of them are needed to monitor one bin.

### RF Link kits
The next iteration of the code will have the MKR 1400 recieve alerts from regular Arduinos about the sensors in the regular Arduinos.

### Arduino Mega
This will be used in the second iteration to control the sensors in the bin and send the alerts or data to the MKR 1400.

## Implementations
### Current Implementation
The current iteration is simple, and only uses the MKR 1400 and the DHT 22 sensors or DFR0198 sensors. It will connect to the cloud and will request data every 15 minutes and if the temperature has changed the cloud will be updated. The frequency of readings can be reduced to save on data charges. This iteration is using the code located in code/ArduinoCloud.

#### Cost
Below I will outline the cost of how much the current implementation would cost for four large bins (about 30ft high). If your bins are larger or smaller you would either need to buy more or less wire, but it should not change the cost that much. The price of the wire put in is what I have got, but your price will probably be different.

#### Hardware Costs
##### With AM2302
| Item            | Price of One                                                                                | Number Needed | Total Cost |
| ------------    |:-----------------------------------------------------------------------------------------------------------------------:| -------------:| ----------:|
| MKR 1400        | [$103.41](https://www.digikey.ca/en/products/detail/arduino/ABX00018/8135631)                                           | 1             | $103.41    |
| DHT 22          | [$21.81](https://www.digikey.ca/en/products/detail/adafruit-industries-llc/393/5356714?s=N4IgTCBcDaIIIFkAEYDMAGCBdAvkA) | 12            | $261.72    |
| Junction Box    | [$25.99](https://www.amazon.ca/gp/product/B075DJQJVY/ref=ppx_yo_dt_b_asin_title_o00_s00?ie=UTF8&psc=1)                  | 1             | $25.99     |
| Wire (per foot) | Varies                                                                                | 300           | $95        |
| Hologram Sim    | [$5.00](https://store.hologram.io/store/)                                                                               | 1             | $5.00      |
| Total           |                                                                                |               | $491.12    |

Note that shipping was not included for any of this.

#### With DFR0198
| Item            | Price of One                                                                                | Number Needed | Total Cost |
| ------------    |:-----------------------------------------------------------------------------------------------------------------------:| -------------:| ----------:|
| MKR 1400        | [$103.41](https://www.digikey.ca/en/products/detail/arduino/ABX00018/8135631)                                           | 1             | $103.41    |
| DFR0198         | [$10.03](https://www.digikey.ca/en/products/detail/dfrobot/DFR0198/7597054)                                             | 12            | $120.36    |
| Junction Box    | [$25.99](https://www.amazon.ca/gp/product/B075DJQJVY/ref=ppx_yo_dt_b_asin_title_o00_s00?ie=UTF8&psc=1)                  | 1             | $25.99     |
| Wire (per foot) | Varies                                                                                | 300           | $95        |
| Hologram Sim    | [$5.00](https://store.hologram.io/store/)                                                                               | 1             | $5.00      |
| Total           |                                                                                |               | $349.76    |

#### Monthly Costs
| Item            | Price                                                                                |
| --------------------- |:-----------------------------------------------------:|
| Arduino Cloud Account | [$9.00 CAD](https://store.arduino.cc/digital/create#) |
| Hologram Data Costs   | $11.80 CAD                                            |
| Total                 | $20.8                                                 |

Note: The data charges will probably be lower since this was calculated on costs when there was no grain in the bin and the temperature varies wildly then.

### Future Improvements
#### RF Link kits
The Arduino Mega has 54 digital pins so it can control many more bins than the MKR 1400 can, however, it cannot connect to the network. The RF link kit will allow the Mega to communication with the MKR 1400 and the MKR 1400 will be able to communicate with the network and send alerts.

#### Email Alerts
This is currently the focus of the work and it will entail the MKR GSM sending data to a third party, possibly IFTTT, which will then send out an email alerting the farmer to a temperature rise.

# Contributing
Please anyone feel free to contribute. It would especially be appreciated if people with more experience on the hardware related, people involved on farms (like me :smiley:) who have experience to what is really needed to help production and save bushels, and people with experience writing software for this type of hardware.

All this being said I do want to stress that those thinking they don't know anything about this, but are still interested in the project please at least contact. We have almost no-one here and even if people don't think it they always have some sort of skill that could be used.

# Final Remarks
Hopefully this project becomes a success and maybe more like could be made!

Thanks for reading all this!

repository: PhysicsUofRAUI/binTempSensor

repo_name: PhysicsUofRAUI/binTempSensor


text:
# shipwhen?
largest worldwide shipping times directory to look up estimated vs. actual business shipping times.

http://www.shipwhen.com

## Demo:
UN: demo PW: DemoUser

In search bar, type in: test

![alt text](src/images/shipwhen-landing-page.png)

## Getting Started
These instructions will get you a copy of the project up and running on your local machine for development and testing purposes. See deployment for notes on how to deploy the project on a live system.

## Prerequisites
https://nodejs.org/en/
https://www.mongodb.com/
https://reactjs.org/
create a mongoDB Atlas account
create a Heroku account

## Installing
A step by step series of examples that tell you how to get a development env running

git clone https://github.com/Laurn17/shipwhen-api
git clone https://github.com/Laurn17/shipwhen-client

cd to each folder respectively

npm install both

Heroku is required for deploying the app, here are the steps to install, create, and deploy to heroku:

npm install -g heroku

Add a file called static.json with:
{
   "root": "build/",
   "routes": {
     "/**": "index.html"
   }
 }

Run: heroku create --buildpack https://github.com/mars/create-react-app-buildpack.git

git push heroku master

## Running the tests
npm test

## Deployment
git push heroku master

heroku ps:scale web=1

## Built With
express - The JS framework used
mongoose - The database client
passport -Authentication middleware
mocha - JS testing framework
React.js - client side libary
Redux.js - client side state management

## Authors
Lauren Morrow - Initial work - Laurn17

Sean Robertson - Help, Edits

## License
This project is licensed under the MIT License - see the LICENSE.md file for details


text:
# Destructuring

MDN Link: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment

ES6 added the ability which is called `destructuring` which essentially allows us to quickly set variables to values inside of `arrays` or `objects`

## Destructuring Arrays

The concept here is pretty easy. So let's take a look

```js
const [my, thing] = ['new', 'one', 'test'];

console.log(my); // Output: 'new'
console.log(thing); // Output: 'one'
```

Catch on what we did there? We created two new variables from our array of values. This follows the index, the good news here is that you can name the vars whatever you want.

The above is essentially the same as:

```js
const arr = ['new', 'one', 'test'];

const my = arr[0];
const var = arr[1];
```

But say we wanted to skip the middle value so we could get our last one?

```js
const [my,, thing] = ['new', 'one', 'test'];

console.log(my); // Output: 'new'
console.log(thing); // Output: 'test'
```

We just leave the center value blank but make sure to place the extra commma, this skips the middle value of one to get us back test.

You can skip any value you need.

```js
const [,my, thing] = ['new', 'one', 'test'];

console.log(my); // Output: 'one'
console.log(thing); // Output: 'test'
```

Pretty nifty right?

## Destructuring Objects

Destructuring objects is similar but different in it's own way. You have to make sure to use the property names when destructuring and object like so:

```js
const { test, things } = {test:  'cool', things: 'features'};

console.log(test); // Output: 'cool'
console.log(things); // Output: 'features'

// If we did something like
const { test } = { thing: 'cool' };

console.log(test); // Output: undefined
```

You cannot however use destructuring to get back values from a nested object

```js
const { things } = { test: { things: 'cool' } }

console.log(things); // Output: undefined

const { test.things } = { test: { things: 'cool' } } // This will throw an error
```

Think of destructuring as a shorthand to calling a value.

```js
const myObj = { test: 'Features' };
const { test } = myObj;

// Is the same as doing this:

const test = myObj.test;
```

You can also change the data to a new name when you destruct an object, like so:

```js
// So we have our object as we had above
const myObj = { test: 'Features' }
// But we already have a const called test!
const test = 'foo'

// Don't worry! we can destruct the object to a different name if we need to!
const { test: baz } = myObj

console.log(test) // => 'foo'
console.log(baz) // => 'Features
```

Notice the formation here, it is identical to the normal object key value pair. In this case it goes

`DataProp: NewVarNAme` so whatever the name of the property you want is on the left side of the colon and the new name is on the right side of the colon.

## Working Code Example

You can checkout the `index.js` file within the example folder to see a working example, to run the example on your machine:

- Clone this Repo
- Navigate to this folder in the terminal
- `cd` into the example folder
- Run `node index.js` to run the example


text:
# Tofino setup
```
                                   __________LOOPBACK__________
_________________           ______|___________________________|_____            _________________
|    Tclust1    |           |                                       |           |    Tclust2    |
|    CLIENT     |___________|                 TOFINO                |___________|    SERVER     |
|               |           |                                       |           |               |
|_______________|           |___17/1__________17/2___________17/3___|           |_______________|
                                 |              |              |
                           ______|______  ______|______  ______|______
                           |   FPGA1   |  |   FPGA2   |  |   FPGA3    |
                           |   bottom  |  |   middle  |  |    top     |
                           |  power #2 |  |  power #3 |  |  power #4  |
                           -------------  -------------  --------------
```

FPGA 1 : Runs KV cache

         Johnshack cable: `jsn-JTAG-SMT2NC-210308A46CBE`

         NOTE: Currently still plugged into arista on port 7/1

FPGA 2 : Runs Encoder

         Johnshack cable: ???? `jsn-JTAG-SMT2NC-210308A47676` ????

FPGA 3 : Runs decoder

         Johnshack cable: ???? `jsn-JTAG-SMT2NC-210308A5F0D3` ????

The tofino dataplane routes packets in the following order:

CLIENT -> FPGA1 -> FPGA2 -> LOOPBACK -> FPGA3 -> SERVER -> CLIENT
           kv       enc      dropper     dec

Start the dataplane with:

`./Run.sh [-f] [-k] -d <drop_rate>`

If `-f` not provided, encoder and decoder will not be used
If `-k` not provided, kv store will not be used
`<drop_rate>` sets the rate at which packets are dropped when sent over the loopback
Only UDP traffic is routed through the cache

repository: eniac/Flightplan

gha_language: C

repo_name: eniac/Flightplan


text:
# OSMJoin
This java program merges multiple JXMapMatchV3 output files and afterwards creates a combined simulation area OSM.xml which only roads where network measurements were conducted on.
The output can afterwards be used to feed the OMNet TBUS model to allow trace-based cellular network simulation. The main functions of this java program are:
- identify different cellular mobile cell sectors
- aggregate and/or filter measurements per road segment
- merge multiple output files of JXMapMatchV3

##Compile
javac OSMJoin.jav

##Run
java OSMJoin

repository: hhucn/OSMJoin

repo_name: hhucn/OSMJoin


text:
---
name: Tracking Issue
about: A tracking issue for a feature
title: Tracking Issue for XXX
labels: C-tracking-issue
---
<!--
Thank you for creating a tracking issue! 📜 Tracking issues are for tracking a
feature from implementation to stabilisation. Make sure to include the relevant
design UML for the feature if it has one. Otherwise provide a short summary of the
feature and link any relevant PRs or issues, and remove any sections that are
not relevant to the feature.

Remember to add team labels to the tracking issue.
Such a feature should also be labeled with e.g., `F-my_feature`.
This label is used to associate issues (e.g., bugs and design questions) to the feature.
-->

### About tracking issues

Tracking issues are used to record the overall progress of implementation.
They are also uses as hubs connecting to other relevant issues, e.g., bugs or open design questions.
A tracking issue is however *not* meant for large scale discussion, questions, or bug reports about a feature.
Instead, open a dedicated issue for the specific matter and add the relevant feature gate label.

### Steps
<!--
Include each step required to complete the feature. Typically this is a PR
implementing a feature, followed by a PR that stabilises the feature. However
for larger features an implementation could be broken up into multiple PRs.
-->

- [ ] Implement the UML
- [ ] Adjust documentation
- [ ] Create PR

### Unresolved Questions
<!--
Include any open questions that need to be answered before the feature can be
stabilised.
-->

XXX --- list all the "unresolved questions" found in the RFC to ensure they are
not forgotten

### Implementation history

<!--
Include a list of all the PRs that were involved in implementing the feature.
-->

gha_license_id: MIT


text:
# inra-server-error

[![npm](https://img.shields.io/npm/v/inra-server-error.svg?maxAge=2592000)](https://www.npmjs.com/package/inra-server-error)
[![Dependency Status](https://david-dm.org/project-inra/inra-server.svg?path=packages/inra-server-error)](https://david-dm.org/project-inra/inra-server.svg?path=packages/inra-server-error)

A simple, yet powerful error handler shipped as a middleware for [Koa](https://koajs.com/).
`inra-server-error` provides a set of utilities for defining and returning HTTP errors. Each utility returns an error response object which includes the following properties:

```json
{
  "success": "…",
  "errorCode": "…",
  "userMessage": "…",
  "developerMessage": "…"
}
```

>**Note**: full documentation with more examples is published on our [Wiki](https://github.com/project-inra/inra-server/wiki). Please, refer to our [Wiki](https://github.com/project-inra/inra-server/wiki) for installation details and API references.

- [Installation](#installation)
- [API reference](#api)
- [Contributing](#contributing)
  - [Bug reporting](#bug-reporting)
  - [Development](#development)

## Installation

```bash
$ npm install --save inra-server-error
```

## API

```javascript
import error, {defineError} from "inra-server-error";
```

#### `error(options)`

Koa errors middleware which catches exceptions thrown inside other middlewares or routes and generates a graceful response.

**Example:**

```javascript
app.use(error({
  errorCode: "Default error code"
  httpStatus: "Default HTTP status",
  userMessage: "Default user message",

  callback(error) {
    // Will be executed on each exception
  }
}));
```

#### `defineError(definition)`

Defines an error handler for a specified exception type.

>**Note:** to make our middleware handle custom errors, you must define an error with exception's instance. Other fields are optional.

**Example:**

```javascript
defineError({
  instance: AuthWrongUsernameError,
  errorCode: "Optional error code"
  httpStatus: "Optional HTTP status",
  userMessage: "Optional user message",

  callback(error) {
    // …
  }
});
```

```javascript
class CustomError extends Error {
  errorCode = 103;
  httpStatus = 401;
  userMessage = "Something went wrong";
};

defineError({
  instance: CustomError
});
```

## Contributing

### Bug reporting

[![Github Open Issues](https://img.shields.io/github/issues-raw/project-inra/inra-server.svg)](https://github.com/project-inra/inra-server/issues)
[![Github Closed Issues](https://img.shields.io/github/issues-closed-raw/project-inra/inra-server.svg)](https://github.com/project-inra/inra-server/issues?q=is%3Aissue+is%3Aclosed)
[![Github Pull Requests](https://img.shields.io/github/issues-pr-raw/project-inra/inra-server.svg)](https://github.com/project-inra/inra-server/pulls)

**We want contributing to Inra Server to be fun, enjoyable, and educational for anyone, and everyone.** Changes and improvements are more than welcome! Feel free to fork and open a pull request. If you have found any issues, please [report them here](https://github.com/project-inra/inra-server/issues/new) - they are being tracked on [GitHub Issues](https://github.com/project-inra/inra-server/issues).

### Development

We have prepared multiple commands to help you develop `inra-server-error` on your own. Don't forget to install all `Node.js` dependencies from [npm](https://www.npmjs.com/). You will need a local copy of [Node.js](https://nodejs.org/en/) installed on your machine.

```bash
$ npm install
```

#### Usage

```bash
$ npm run <command>
```

#### List of commands

| Command | Description                              |
| ------- | ---------------------------------------- |
| `build` | Builds `inra-server-error`               |
| `watch` | Re-builds `inra-server-error` on changes |
| `clean` | Deletes builds ands cache                |
| `lint`  | Fixes Lint errors                        |
| `flow`  | Checks Flow errors                       |
| `test`  | Checks Flow errors and runs tests        |

repository: project-inra/inra-server

branch_name: refs/heads/development

gha_language: JavaScript

repo_name: project-inra/inra-server


text:
Birthday Reminder

    Python Application | 10 lines of code + Video Explanation 🧭

You can create a normal birthday reminder program using `python`. You need to set the date and time of the birthday and reminder and you'll get an reminder of your or your friend's birthday notification. But I feel that this program is useless because you've to keep this code runnig... we can create a notification to make this code cooler and ready to public use. Well, develop and add features to this code mr. `Developer` `Researcher`
 ```
What the program does?

- User will select birthday
- User will select time of the reminder
- In that day | time program will wish her/him a happy birthday ❤
```
### Requirements

* Python
* Python Libraries: `datetime`

### Contributing

Any kind of contributions to `qxresearch-event-1/birthday-reminder` are welcome. While creating an issue(for this project) use `Birthday-Reminder` Label.

1. [Fork](https://github.com/qxresearch/qxresearch-event-1/fork) the Project
2. Commit your Changes
3. Open a [Pull Request](https://github.com/qxresearch/qxresearch-event-1/pulls)

### Video Tutorial

* **YouTube :** [Birthday Reminder](https://youtu.be/qHloV2ZCo4s)

### Become Official Member @qxresearch

* Join Mozilla Group [@qxresearch](https://community.mozilla.org/en/groups/qx-research/)
* Join Telegram Group [@qxresearch](https://t.me/qxresearch)
* <a href = "mailto<EMAIL_ADDRESS>me your GitHub id (**subject**: GitHub id @qxresearch)

    View Demo
    ·
    Report Bug
    ·
    Request Feature


text:
# Markdown Previewer

### Roadmap
  - [x] Stylesheets. Right now it looks very crappy. Maybe just import Github's css.
  - [ ] Set title to the same as the file that is being read.
  - [x] Load filename from query string: `/foo.md` instead of using flag.

### Installation
Grab the latest release for your platform [here](https://github.com/mongrelion/mdp/releases).
It's a binary file and it works out of the box.

Alternatively, if you have Go installed, you can install it using the `go install` command:

```
$ go intall https://github.com/mongrelion/mdp
```

### Usage
Run it with
```
$ mdp
```

By default it listens on http://localhost:8080/
For example, if you want to render the `README.md` file then you must access it via http://localhost:8080/README.md.
Subdirectories are also valid: http://localhost:8080/post/2016/foobar.md

```
$ mpd --help
Usage of mdp:
-bind string
  interface to bind to, eg. <IP_ADDRESS>:8080 (default ":8080")
-version
  prints out the version
```

repository: mongrelion/mdp

repo_name: mongrelion/mdp


text:
# Simple Guestbook

Simple guestbook built with Lumen and VueJs,
inspired by [Laracasts guestbook](https://github.com/laracasts/Laravel-and-Vue)
but a little bit different, and better.

<del>You can find a demo hosted on my personal site's guestbook [Guestbook](http://claudioludovico.panetta.it/guestbook)</del>

# How to install

* Clone this repository or download it
* Open terminal and run `composer install`
* Create a `database.sqlite` file in `storage/`
* Open terminal and run `php artisan migrate`
* Open terminal and run `vendor/bin/phpunit` to run little tests
* Enjoy

# Contribute

Feel free to submit issues, pull request or whatever you want :+1:


text:
---
title: Getting Started
page_title: Getting Started
description: Getting Started
slug: radribbonview-gettingstarted
tags: getting,started
published: True
position: 0
---

# Getting Started

__RadRibbonView__ is an advanced {% if site.site_name == 'Silverlight' %}Silverlight{% endif %}{% if site.site_name == 'WPF' %}WPF{% endif %} control providing full Blend support. From within the visual environment of Blend, you can easily perform various tasks such as editing control properties, modifying themes, creating and modifying templates and more.

This tutorial will walk you through the creation of a __RadRibbonView__.

>Before reading this tutorial you should get familiar with the [Visual]({%slug radribbonview-visual-structure%}) and [Functional]({%slug radribbonview-functional-structure%}) structure of the standard __RadRibbonView__ control.

For the purpose of this tutorial, you will need to create an empty {% if site.site_name == 'Silverlight' %}Silverlight{% endif %}{% if site.site_name == 'WPF' %}WPF{% endif %} Application project and open it in Blend.

{% if site.site_name == 'Silverlight' %}
>In order to use __RadRibbonView__ control in your projects you have to add references to the following assemblies:
>	- __Telerik.Windows.Controls__
>	- __Telerik.Windows.Controls.Input__
>	- __Telerik.Windows.Controls.Navigation__
>	- __Telerik.Windows.Controls.RibbonView__

>You can find more info [here](http://www.telerik.com/help/silverlight/installation-installing-controls-dependencies.html).
{% endif %}

{% if site.site_name == 'WPF' %}
>In order to use __RadRibbonView__ control in your projects you have to add references to the following assemblies:
>	- __Telerik.Windows.Controls__
>	- __Telerik.Windows.Controls.Input__
>	- __Telerik.Windows.Controls.Navigation__
>	- __Telerik.Windows.Controls.RibbonView__
>	- __Telerik.Windows.Data__

>You can find more info [here](http://www.telerik.com/help/wpf/installation-installing-controls-dependencies-wpf.html).
{% endif %}

## Add RadRibbonView Using Expression Blend

* Open the __Asset Library__ (*Window->Assets*) in Expression Blend and start writing the name of the __RadRibbonView__ in the search box.
	![](images/RibbonView_gettingstarted_add.png)

* Drag a __RadRibbonView__ on the artboard.
	![](images/RibbonView_gettingstarted_artboard.png)

	#### __XAML__

	{{region radribbonview-gettingstarted_0}}
		<UserControl
		 ...
		 xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
		 ...>
		 <Grid x:Name="LayoutRoot" Background="White">
		  <telerik:RadRibbonView />
		 </Grid>
		</UserControl>
	{{endregion}}

	There are two things you should pay attention to in the above code snippet. The first is the declaration of the __telerik__ namespace from and the second is the declaration of the __RadRibbonView__ control itself.

If you run your application now you will see an empty __RadRibbonView__ that contains no tabs, no application/backstage menu and no elements. To learn about each one of the controls, that the __RadRibbonView__ may contain, check out the __Ribbon Controls__ subsection in the __Features__ section.

## Add Application Icon

In order to add an application icon perform the following instructions:

* Select your control in Expression Blend.

* In the __Properties Pane__, find the __ApplicationButtonImageSource__ property and select the desired image from your local hard drive.
	![](images/RibbonView_appBtnImage.png)

	#### __XAML__

	{{region radribbonview-gettingstarted_1}}
		<telerik:RadRibbonView ApplicationButtonImageSource="AppIcon.png" />
	{{endregion}}

Note that the selected image will be included in your project.![](images/RibbonView_DisplayAppBtnImage.png)

## Set Application Title

In order to set the application title, you need to use the __RadRibbonView__'s __Title__ property. This can be done in two easy steps:

* Select your RibbonView control in Expression Blend

* In the __Properties Pane__, find the __Title__ property and set its value.
	![](images/RibbonView_setTitle.png)

	#### __XAML__

	{{region radribbonview-gettingstarted_2}}
		<telerik:RadRibbonView ApplicationButtonImageSource="AppIcon.png" Title="Microsoft Word" />
	{{endregion}}

The result can be seen on the next snapshot.
![](images/RibbonView_DisplayTitle.png)

## Add Ribbon Tabs

The __RadRibbonView__ helps end-users to quickly find the tools and options they need in order to complete a task. Tools and options are organized in logical groups that are collected together under specific __tabs__. Or in other words - the __Ribbon Tab__ lets you categorize the commands to be displayed for the end-users.

>The class that represents the ribbon tab is __Telerik.Windows.Controls.RadRibbonTab__.

In order to add ribbon tabs to your ribbon control in Expression Blend, you should perform the following instructions:

* Select your RibbonView control.

* In the __Properties Pane__, find and edit the __Items__ property.
	![](images/RibbonView_GettingStarted_AddItems.png)

* The "Object Collection Editor" dialog will open.
	![](images/RibbonView_GettingStarted_AddNewItem.png)

* Add two items of type __RadRibbonTab__.
	![](images/RibbonView_GettingStarted_ItemType.png)

* Set their __Header__ properties respectively to "Header" and "View". The result from the operations above is shown on the next image.
	![](images/RibbonView_GettingStarted_DisplayTabs.png)

#### __XAML__

{{region radribbonview-gettingstarted_3}}
	<telerik:RadRibbonView ApplicationButtonImageSource="AppIcon.png" Title="Microsoft Word" >
	 <telerik:RadRibbonTab Header="Home"/>
	 <telerik:RadRibbonTab Header="View"/>
	</telerik:RadRibbonView>
{{endregion}}

For more information about the __RadRibbonTab__, check out the [Ribbon Tab]({%slug radribbonview-ribbon-tab%}) topic in the __Ribbon Controls__ section

## Add Content to the Ribbon Tabs

The content of the ribbon is inserted into the __RadRibbonGroups__ which are rendered inside the __RadRibbonTabs__.

* In the "Object and Timeline" pane in Expression Blend, select the first __RadRibbonTab__.
	![](images/RibbonView_gettingstarted_select_firstTab.png)

* Using the __RadRibbonTab__'s __Items__ property add a new item of type __RadRibbonGroup__. Set its __Header__ property to "Clipboard".
	![](images/RibbonView_GettingStarted_display_EpmtyGroup.png)

	The result XAML so far is shown on the next code-snippet.

	#### __XAML__

	{{region radribbonview-gettingstarted_4}}
		<telerik:RadRibbonView ApplicationButtonImageSource="AppIcon.png" Title="Microsoft Word" >
			<telerik:RadRibbonTab Header="Home">
				<telerik:RadRibbonGroup Header="Clipboard"/>
			</telerik:RadRibbonTab>
			<telerik:RadRibbonTab Header="View"/>
		</telerik:RadRibbonView>
	{{endregion}}

	For more information about the ribbon group, read the main [Ribbon Group]({%slug radribbonview-ribbon-group%}) topic.

* The final step is to add content to the ribbon group. You should again use the __Items__ property, however this time you use the __Items__ property of the __RadRibbonGroup__ object.

	For example, the next code snippet adds a __RadRibbonSplitButton__ as a child of the group.

	#### __XAML__

	{{region radribbonview-gettingstarted_5}}
		<telerik:RadRibbonView ApplicationButtonImageSource="AppIcon.png" Title="Microsoft Word">
			<telerik:RadRibbonTab Header="Home">
				<telerik:RadRibbonGroup Header="Clipboard">

					<telerik:RadRibbonSplitButton Text="Paste" LargeImage="paste.png" Size="Large"
							telerik:ScreenTip.Title="Paste(Ctrl+V)"
							telerik:ScreenTip.Description="Paste the contents the Clipboard.">
						<telerik:RadRibbonSplitButton.DropDownContent>
							<telerik:RadContextMenu BorderThickness="0">
								<telerik:RadMenuItem Header="Paste" />
								<telerik:RadMenuItem Header="Paste Form" />
							</telerik:RadContextMenu>
						</telerik:RadRibbonSplitButton.DropDownContent>
					</telerik:RadRibbonSplitButton>

				</telerik:RadRibbonGroup>
			</telerik:RadRibbonTab>
			<telerik:RadRibbonTab Header="View" />
		</telerik:RadRibbonView>
	{{endregion}}

	![](images/RibbonView_GettingStarted_AddSplitButton.png)

There are two things you should pay attention to in the above code snippet. The first is the declaration of the __RadRibbonSplitButton__ and its drop down content. In fact the __RadRibbonView__'s API exposes several __buttons__ you could use with the ribbon. For more information, check out tha [RibbonButtons - Overview]({%slug radribbonview-buttons-overview%}) topic. The second is the declaration of the __screen tips__. __Screen Tip__ is a UI feature in which a small window appears when the __mouse cursor__ is hovered over an icon or a ribbon element (command). The __popup__ window will provide details that explain the command's function. For more information see the [Screen Tips]({%slug radribbonview-screentips%}) topic.

## Declare Backstage

The __Backstage Menu__ is equivalent to the __File__ menu of the traditional menu UIs. It is represented by the rectangular button (named __Application Button__) on the upper-left corner of the __RadRibbonView__ control. The __Backstage Menu__ appears when a user __clicks__ the __Application Button__. This menu displays controls used to perform actions on the entire document, like Save, Print and Send. The __Backstage Menu__ also provides a list of recent documents, access to application options for changing user settings and preferences, and application exit.

To declare a Backstage menu you need to set the __Backstage__ property like the example below.

#### __XAML__

{{region radribbonview-gettingstarted_6}}
	<telerik:RadRibbonView ApplicationButtonImageSource="AppIcon.png" Title="Microsoft Word">
	    <telerik:RadRibbonView.Backstage>
	        <telerik:RadRibbonBackstage>
	            <telerik:RadRibbonBackstageItem CloseOnClick="False" Header="Save" Icon="Images/Save.png"
	                    IsSelectable="False" />
	            <telerik:RadRibbonBackstageItem Header="Save As" Icon="Images/SaveAs.png" IsSelectable="False" />
	            <telerik:RadRibbonBackstageItem Header="Open" Icon="Images/Open.png" IsSelectable="False" />
	            <telerik:RadRibbonBackstageItem Header="Separator" IsGroupSeparator="True" />
	            <telerik:RadRibbonBackstageItem Header="Recent" IsDefault="True">
	                <Grid>
	                    <Grid.ColumnDefinitions>
	                        <ColumnDefinition Width="*" />
	                        <ColumnDefinition Width="Auto" />
	                        <ColumnDefinition Width="*" />
	                    </Grid.ColumnDefinitions>
	                    <StackPanel Margin="15 15 0 0">
	                        <TextBlock Margin="0 0 0 2" FontSize="14" FontWeight="Bold" Text="Recent Pictures" />
	                        <Rectangle Height="1">
	                            <Rectangle.Fill>
	                                <LinearGradientBrush MappingMode="Absolute" SpreadMethod="Repeat"
	                                        StartPoint="0,0.5" EndPoint="4,0.5">
	                                    <GradientStop Offset="0" Color="#40000000" />
	                                    <GradientStop Offset="0.5" Color="#40000000" />
	                                    <GradientStop Offset="0.501" Color="Transparent" />
	                                </LinearGradientBrush>
	                            </Rectangle.Fill>
	                        </Rectangle>
	                        <ItemsControl Margin="0 4 0 0">
	                            <telerik:RadRibbonButton Content="1 Untitled.png" HorizontalAlignment="Stretch" />
	                            <telerik:RadRibbonButton Content="2 TelerikLogo.png" HorizontalAlignment="Stretch" />
	                            <telerik:RadRibbonButton Content="3 Silverlight 3.png" HorizontalAlignment="Stretch" />
	                            <telerik:RadRibbonButton Content="4 Test.png" HorizontalAlignment="Stretch" />
	                        </ItemsControl>
	                    </StackPanel>
	                </Grid>
	            </telerik:RadRibbonBackstageItem>
	            <telerik:RadRibbonBackstageItem Header="Exit" Icon="Images/Exit.png" IsSelectable="False" />
	        </telerik:RadRibbonBackstage>
	    </telerik:RadRibbonView.Backstage>
	    <telerik:RadRibbonTab Header="Home">
	        <telerik:RadRibbonGroup Header="Clipboard">
	            <telerik:RadRibbonSplitButton Text="Paste" LargeImage="paste.png" Size="Large"
	                    telerik:ScreenTip.Title="Paste(Ctrl+V)"
	                    telerik:ScreenTip.Description="Paste the contents the Clipboard.">
	                <telerik:RadRibbonSplitButton.DropDownContent>
	                    <telerik:RadContextMenu BorderThickness="0">
	                        <telerik:RadMenuItem Header="Paste" />
	                        <telerik:RadMenuItem Header="Paste Form" />
	                    </telerik:RadContextMenu>
	                </telerik:RadRibbonSplitButton.DropDownContent>
	            </telerik:RadRibbonSplitButton>
	        </telerik:RadRibbonGroup>
	    </telerik:RadRibbonTab>
	    <telerik:RadRibbonTab Header="View" />
	</telerik:RadRibbonView>
{{endregion}}

The result is shown on the next image.
![](images/RibbonView_GettingStarted_Backstage.png)

For more information see the [Backstage]({%slug radribbonview-ribbon-backstage%}) topic.

## Declare Quick Access Toolbar

The __Quick Access Toolbar__ is used to render a set of __RadRibbonView__ controls (commands) that are most commonly used in the application. It is rendered right above the ApplicationButton to make it easily accessible to end-users. To declare the Quick Access ToolBar you need to set the __QuickAccessToolBar__ property. For more information and practical example, refer to the [Quick Access Toolbar]({%slug radribbonview-qat%}) topic.

## Resizing

One of the most important features of the __RadRibbonView__ is the dynamic layout resizing. It refers to the __RadRibbonView__'s ability to optimize its layout depending on how much space is available. This process can't be automated, however, the __RadRibbonView__'s API gives you the ability to specify how you would like the resizing to occur. Check out the following topics, which are tightly connected to the resizing behavior:

* [Resizing]({%slug radribbonview-resizing%})
* [Ordered Wrap Panel]({%slug radribbonview-ordered-wrap-panel%})
* [Collapsible Panel]({%slug radribbonview-collapsible-panel%})

# See Also
 * [Ribbon Backstage]({%slug radribbonview-ribbon-backstage%})
 * [Application Menu]({%slug radribbonview-applicationmenu%})
 * [Quick Access Toolbar]({%slug radribbonview-qat%})
 * [Ribbon Tab]({%slug radribbonview-ribbon-tab%})

repository: SteliyanStoyanov/xaml-docs

repo_name: SteliyanStoyanov/xaml-docs


text:
# Testing

## Mocks
Mocks are generated using [mockery](https://github.com/vektra/mockery).

To regenerate gateway mock go to the gateway directory `/pkg/flowkit/gateway` and run the command:
```shell
mockery --name=Gateway --output ../../../tests/mocks
```

repository: jrkhan-bot/flow-cli

gha_language: Go

repo_name: jrkhan-bot/flow-cli


text:
[![Build status](https://ci.appveyor.com/api/projects/status/gwtbg5j0tvde2kty?svg=true)](https://ci.appveyor.com/project/johtela/extensioncord)
[![NuGet Version](https://img.shields.io/nuget/v/ExtensionCord.svg)](https://www.nuget.org/packages/ExtensionCord)

# ExtensionCord - Useful Extensions for .NET Types

This assembly contains useful extension methods for standard .NET types and some simple
helper classes. It is an assortment of code that I tend to reuse in most of my projects.
So, instead of copying that code around, I collected it into a single shared assembly.

## Installation

The latest version of the library can be installed as a
[Nuget package](https://www.nuget.org/packages/ExtensionCord) from [nuget.org](https://www.nuget.org/).
The library targets .NET standard 1.0, so it works with practically all .NET implementations.

## Documentation

Documentation can be found in <https://johtela.github.io/ExtensionCord/>.

repository: johtela/ExtensionCord

repo_name: johtela/ExtensionCord


text:
# doveadm-tools
**doveadm-tools** - wrapper scripts set for the Dovecot's administration utility doveadm(1):

* **doveadm-backup** - performs one-way synchronization of mailboxes
 from Dovecot's mail storage to a local directory or via tcp connection.

* **doveadm-expunge** - expunges messages in `Junk` and `Trash` folders and purges mailboxes for every user.

* **doveadm-mdboxrm** - removes SIS enabled user's mdbox storages.

* **doveadm-report-last-login** - prints Dovecot last-login dictionary file in human readable form.

* **doveadm-report-quota** - shows current quota usage.

* **doveadm-rm-attachments** - removes attachments from messages that match the criteria specified via options.

* **doveadm-rm-savedbefore** - removes messages, which were saved before the given date specification.

* **dsisck** - Dovecot SIS consistency check and repair. Based on explanation of SIS operation [1](#fn1),[2](#fn2),[3](#fn3). Main purpose of this program is to deduplicate identical attachments that was saved in separate files for some reason. For instance, attachment deduplication was broken in Dovecot v2.2.16 upwards and fixed in v2.2.22. Every attachment was saved in a separate file.

## References
1. http://www.dovecot.org/list/dovecot/2010-August/052175.html
2. http://dovecot.org/list/dovecot/2010-July/050832.html
3. http://dovecot.org/list/dovecot/2010-July/050992.html

repository: moisseev/doveadm-tools

repo_name: moisseev/doveadm-tools


text:
---
title: "SendGrid"
meta_title: "SendGrid"
meta_description: "How to receive notifications from Polyaxon directly to your email using Sendgrid. Get email notifications when an experiment, job, build is finished using Sendgrid so that your team stays in sync."
custom_excerpt: "SendGrid is a cloud-based SMTP provider that acts as an email delivery engine, allowing you to send email without the cost and complexity of maintaining your own email servers."
image: "../../content/images/integrations/sendgrid.jpg"
author:
  name: "Polyaxon"
  slug: "Polyaxon"
  website: "https://polyaxon.com"
  twitter: "polyaxonAI"
  github: "polyaxon"
tags:
  - notifications
  - email
featured: false
popularity: 0
visibility: public
status: published
---

Get email notifications when an experiment, a job, or a build is finished using Sendgrid so that your team stays in sync.

## Start by creating a Sendgrid account

[Sendgrid](https://sendgrid.com/solutions/smtp-service/) makes it easy to set up an smtp email service.

## Add your Email notification using Sendgrid to Polyaxon deployment config

Now you can set the email section using your Sendgrid's information:

```yaml
email:
  host: "smtp.sendgrid.net"
  port: 587
  useTls: true
  hostUser: "sendgrid_username"
  hostPassword: "123456"
```

repository: polyaxon/polyaxon

gha_language: Python

repo_name: polyaxon/polyaxon


text:
- [x] [Fast subword permutation instructions based on butterfly networks](http://www.princeton.edu/~rblee/PUpapers/xiao_spie00.pdf?q=tilde/rblee/PUpapers/xiao_spie00.pdf)

- [ ] [more resources to be added from notes] ... (phone?) <sup>`TODO:find`</sup>

### Related:

- [[Bit permutations]]
- [[Dimension permutations]] (_Bit-permute/complement permutations_)

## See also:

- [[Permutation groups (Alan Turing)]]

repository: copermut/syn

repo_name: copermut/syn


text:
# GAUSS-02691 -- GAUSS-02700

GAUSS-02691: "type %u not supported as catcache key"

SQLSTATE: XX000

Description:Internal system error.

Solution:Contact technical support.

GAUSS-02692: "wrong number of hash keys: %d"

SQLSTATE: XX000

Description:Internal system error.

Solution:Contact technical support.

GAUSS-02693: "only sys attr supported in caches is OID"

SQLSTATE: XX000

Description:Internal system error.

Solution:Contact technical support.

GAUSS-02694: "operator %u is not a member of opfamily %u"

SQLSTATE: XX000

Description:Internal system error.

Solution:Contact technical support.

GAUSS-02695: "operator %u does not exist"

SQLSTATE: XX000

Description: An expression is invalid.

Solution: Check whether the expression in the query is valid. If not, modify the query.

GAUSS-02696: "binary I/O not supported during bootstrap"

SQLSTATE: XX000

Description:Internal system error.

Solution:Contact technical support.

GAUSS-02697: "invalid syntax for type: '%s'"

SQLSTATE: 22023

Description:Internal system error.

Solution:Contact technical support.

GAUSS-02698: "cache lookup failed for node %u"

SQLSTATE: XX000

Description:Internal system error.

Solution:Contact technical support.

GAUSS-02699: "cache lookup failed for group %u"

SQLSTATE: XX000

Description:Internal system error.

Solution:Contact technical support.

GAUSS-02700: "cache lookup failed on distribution relation %u"

SQLSTATE: XX000

Description:Internal system error.

Solution:Contact technical support.


text:
# A multiverse analysis of the associations between internet use and well-being

This repository contains the code and simulated dataset associated with "A multiverse analysis of the associations between internet use and well-being" (Vuorre & Przybylski).

- https://doi.org/10.5281/zenodo.7774923
- https://github.com/digital-wellbeing/gwp-multiverse

## Data

The Gallup dataset that we used is not publicly available. For researchers who have access to this dataset, place it in `data-raw/gallup/The_Gallup_042722.sav` to exactly reproduce our analyses. For other researchers, we have placed a simulated smaller dataset in `synthetic-data/synthetic-data.csv.gz`.

## Reproduce

0a. If you have access to the Gallup dataset, place the provided SPSS data file in `data-raw/gallup/The_Gallup_042722.sav`.
0b. If you do not have access to the Gallup dataset, uncomment the line in `ms.Rmd` that loads the synthetic dataset instead.
1. Recreate our R environment provided with {renv}: <https://cloud.r-project.org/web/packages/renv/index.html>
2. "knit" the `ms.Rmd` file. (e.g. `rmarkdown::render('ms.Rmd')`.)
3. (Optional) email Matti at<EMAIL_ADDRESS>if you are unable to run the code.

repository: digital-wellbeing/gwp-multiverse

repo_name: digital-wellbeing/gwp-multiverse


text:
# Detective Droid
[![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-detective--droid-brightgreen.svg?style=flat)](https://android-arsenal.com/details/1/898) [![Maintainability](https://api.codeclimate.com/v1/badges/4dae723e17c6fadb28a9/maintainability)](https://codeclimate.com/github/michaelcarrano/detective-droid/maintainability) [![Test Coverage](https://api.codeclimate.com/v1/badges/4dae723e17c6fadb28a9/test_coverage)](https://codeclimate.com/github/michaelcarrano/detective-droid/test_coverage) [![CircleCI](https://circleci.com/gh/michaelcarrano/detective-droid.svg?style=svg)](https://circleci.com/gh/michaelcarrano/detective-droid)

Detective Droid is here to help you investigate what libraries are being used inside applications that are installed on your device.

This makes it really easy to see what other developers/companies are using to develop their applications.

Detective Droid requires no permissions and works on Android API 21 (Android 5.0 Lollipop) and newer.

- **Andriod 11**: Changes in Android 11 require a permission in order to get the list of apps installed on the user's device. You can read more about this change: [https://developer.android.com/preview/privacy/package-visibility](https://developer.android.com/preview/privacy/package-visibility)

## Limitations
Detective Droid is unable to detect libraries that are obfuscated with Proguard/R8. Additionally, unable to detect libraries that are dynamically created. For instance, [LeadBolt](http://leadbolt.com) creates their SDK on the fly for each developer which means a unique Classpath.

## Credits
Daniel Bjorge - Detective Droid is inspired by his [AirPush Detector](https://github.com/dbjorge/AirPush-Detector) project.

Josef Pfleger - The logic of detecting libraries in other applications comes from his article, [APK piracy](http://www-jo.se/f.pfleger/apk-piracy).

## License

    Copyright 2013 Michael Carrano

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

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

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

repository: michaelcarrano/detective-droid

gha_language: Kotlin

repo_name: michaelcarrano/detective-droid


text:
# Facebook Cookbooks Suite

[![Continuous Integration](https://github.com/facebook/chef-cookbooks/workflows/Continuous%20Integration/badge.svg?event=push)](https://github.com/facebook/chef-cookbooks/actions?query=workflow%3A%22Continuous+Integration%22)

This repo contains attribute-driven-API cookbooks maintained by Facebook. It's
a large chunk of what we refer to as our "core cookbooks."

It's worth reading our
[Philosophy.md](https://github.com/facebook/chef-utils/blob/main/Philosophy.md)
doc before reading this. It covers how we use Chef and is important context
before reading this.

It is important to note that these cookbooks are built using a very specific
model that's very different from most other cookbooks in the community.
Specifically:

* It assumes an environment in which you want to delegate. The cookbooks are
  designed to be organized in a "least specific to most specific" order in the
  run-list. The run-list starts with the "core cookbooks" that setup APIs and
  enforce a base standard, which can be adjusted by the service owners using
  cookbooks later in the run-list.
* It assumes a "run from main" type environment. At Facebook we use [Grocery
  Delivery](http://www.github.com/facebook/grocery-delivery) to sync the main
  branch of our source control repo with all of our Chef servers. Grocery
  Delivery is not necessary to use these cookbooks, but since they were built
  with this model in mind, the versions never change (relatedly: we do not use
  environments).
* It assumes you have a testing toolset that allows anyone modifying later
  cookbooks to ensure that their use of the API worked as expected on a live
  node before committing. For this, we use [Taste
  Tester](http://www.github.com/facebook/taste-tester).

Cookbooks in this repo all being with `fb_` to denote that not only do they
use the Facebook Cookbook Model, but that they are maintained in this repo.

Local cookbooks or cookbooks in other repositories that implement this model
should not use this prefix, but should reference this document in their docs.

## APIs

Unlike other cookbook models, we do not use resources as APIs, we use the node
object. Configuration is modeled in arrays and hashes as closely and thinly as
possible to the service we are configuring. Ideally, you should only have to
read the docs to the service to configure it, not the docs to the cookbook.

For example, if the service we are configuring has a key-value pair
configuration file, we will provide a simple hash where keys and values will be
directly put into the necessary configuration file.

There are two reasons we use attribute-driven APIs:

1. Cascading configuration
   Since our cookbooks are ordered least specific (core team that owns Chef) to
   most specific (the team that owns this machine or service) it means that the
   team who cares about this specific instance can always override anything.
   This enables stacking that is not possible in many other models. For
   example, you can have a run-list that looks like:

   * Core cookbooks (the ones in this repo)
   * Site/Company cookbooks (site-specific settings)
   * Region cookbooks (overrides for a given region/cluster)
   * Application Category cookbooks (webserver, mail server, etc.)
   * Specific Application cookbook ("internal app1 server")

   So let's say that you want a specific amount of shared memory by default,
   but in some region you know you have different size machines, so you shrink
   it, but web servers need a further different setting, and then finally some
   specific internal webserver needs an even more specific setting... this all
   just works.

   Further, a cookbook can see the value that was set before it modifies
   things, so the 'webserver' cookbook could look to see what the value was
   (small or large) before modifying it and adjust it accordingly (so it could
   be relative to the size of memory that the 'region' cookbook set).

   Using resources for this does not allow this "cascading", it instead creates
   "fighting". If you use the cron resource to setup an hourly job, and then
   someone else creates a cron for that same job but only twice a day, then
   during each Chef run the cron job gets modified to hourly, then re-modified
   to twice a day.

2. Allows for what we refer to as "idempotent systems" instead of "idempotent
   settings." In other words, if you only manage a specific item in a larger
   config, and then you stop managing it, it should either revert to a
   less-specific setting (see #1) or be removed, as necessary.

   For example let's say you want to set a cron job. If you use the internal
   cron resource, and then delete the recipe code that adds that cronjob, that
   cron isn't removed from your production environment - it's on all existing
   nodes, but not on any new nodes.

   For this reason we use templates to take over a whole configuration wherever
   possible. All cron jobs in our `fb_cron` API are written to
   `/etc/cron.d/fb_crontab`. If you delete the lines adding a cronjob, since
   they are just entries in a hash, when the template is generated on the next
   Chef run, those crons go away.

   Alternatively, consider a sysctl set by the "site" cookbook, then
   overwritten by a later cookbook. When that later code is removed, the entry
   in the hash falls back to being set again by the next-most-specific value
   (i.e. the "site" cookbook in this case).

## Run-lists

How you formulate your run-lists is up to your site, as long as you follow the
basic rule that core cookbooks come first and you order least-specific to
most-specific. At Facebook, all of our run-lists are:

    recipe[fb_init], recipe[$SERVICE]

Where `fb_init` is similar to the sample provided in this repo, but with extra
"core cookbooks."

We generally think of this way: `fb_init` should make you a "Facebook server"
and the rest should make you a whatever-kind-of-server-you-are.

## Getting started

Grab a copy of the repo, rename `fb_init_sample` to `fb_init`, and follow the
instructions in its [README.md](https://github.com/facebook/chef-cookbooks/blob/main/cookbooks/fb_init_sample/README.md)
(coordinating guidance is in comments in the default recipe).

## Other Guidelines

### Modules and classes in cookbooks

It is often useful to factor out logic into a library - especially logic that
doesn't create resources. Doing so makes this logic easier to unit test and
makes the recipe or resource cleaner.

Our standard is that all cookbooks use the top-level container of `module FB`,
and then create a class for their cookbook under that. For example, `fb_fstab`
creates a `class Fstab` inside of the `module FB`. We will refer to this as
the cookbook class from here.

We require all cookbooks use this model for consistency.

Since we don't put anything other than other classes inside the top-level
object, it's clear that a `module` is the right choice.

While there is no reason that a cookbook class can't be one designed to be
instantiated, more often than not it is simply a collection of class methods
and constants (i.e. static data and methods that can then be called both from
this cookbook and others).

Below the cookbook class, the author is free to make whatever class or methods
they desire.

When building a complicated Custom Resource, the recommended pattern is to
factor out the majority of the logic into a module, inside of the cookbook
class, that can be `include`d in the `action_class`. This allows the logic to
be easily unit tested using standard rspec. It is preferred for this module to
be in its own library file, and for its name to end in `Provider`, ala
`FB::Thing::ThingProvider`.

When more than 1 or 2 methods from this module are called from the custom
resource itself, it is highly recommended you include it in a Helper class for
clarity, ala:

```
action_class do
  class ThingHelper
    include FB::Thing::ThingProvider
  end
end
```

In this way, it is clear where methods come from.

### Extending the node vs self-contained classes

You may have noticed that some of our cookbooks will extend the `node` object,
while others have self-contained classes that sometimes require the `node` be
passed as a parameter to some methods.

In general, the **only** time when extending the `node` is acceptable is when
you are simply making a convenience function around using the node object. So,
for example, instead of making people do `node['platform_family'] = 'debian'`,
there's a `node.debian?`. This is simply syntactic sugar on top of data
entirely in the node.

In all other cases, one should simply have the `node` be an argument passed on,
so as to not pollute the node namespace. For example, a method that looks at
the node attributes, but also does a variety of other logic, should be in a
cookbook class and take the node as an argument (per standard programming
paradigms about clear dependencies).

### Methods in recipes

Sometimes it is convenient to put a method directly in a recipe. It is strongly
preferred to put these methods in the cookbook class, however there are some
cases where methods directly in recipes make sense. The primary example is a
small method which creates a resource based on some input to make a set of
loops more readable.

### Methods in templates

Methods should not be put into templates. In general, as little logic as
possible should be in templates. In general the easiest way to do this is to
put the complex logic into methods in your cookbook class and call them from
the templates.

### Err on the side of fail

Chef is an ordered system and thus is designed to fail a run if a resource
cannot be converged. The reason for this is that if one step in an ordered
list cannot be completed, it's likely not safe to do at least some of the
following steps. For example, if you were not able to write the correct
configuration for a service, then starting it may open up a security
vulnerability.

Likewise, the Facebook cookbooks will err on the side of failing if something
seems wrong. This is both in line with the Chef philosophy we just outlined,
but also because this model assumes that code is being tested on real systems
before being released using something like [taste-tester](https://github.com/facebook/taste-tester/) and that monitoring is
in place to know if your machines are successfully running Chef.

Here are some examples of this philosophy in practice:

* If a cookbook is included on a platform it does not support, we `fail`. It
  might seem like `return`ing in this case is reasonable but there is a good
  indication the run-list isn't as-expected, so it's a great idea to bail out
  before this machine is mis-configured.
* If a configuration was passed in that we don't support, rather than ignore it
  we `fail`.

### Validation of inputs and `whyrun_safe_ruby_blocks`

Many cookbooks rely on the service underneath and the testing of the user to be
the primary validator of inputs. Is the software we just configured, behaving
as expected?

However, sometimes it's useful to do our own validation because there are
certain configurations we don't want to support, because the software may
accepted dangerous configurations we want to catch, or because the user could
pass us a combination of configurations that is conflicting or impossible to
implement.

In this model, however, this must be done at runtime. If your implementation is
done primarily inside of an internally-called resource, then this validation
can also be done there. However, if your implementation is primarily a recipe
and templates, doing the validation in templates is obviously not desirable.
This is where `whyrun_safe_ruby_blocks` come in.

Using an ordinary `ruby_block` would suffice to have ruby code run at runtime
to validate the attributes, however that means that the error would not be
caught in whyrun mode. Since this validation does not change the system, it is
safe to execute in whyrun mode, and that's why we use `whyrun_safe_ruby_block`s:
they are run in whyrun mode.

It is worth noting that this is also where you can take input that perhaps was
in a structure convenient for users and build out a different data structure
that's more convenient to use in your template.

### Implementing runtime-safe APIs

This model intentionally draws the complexity of Chef into the "core cookbooks"
(those implementing APIs) so that the user experience of maintaining systems is
simple and (usually) requires little more than writing to the node object.
However, the trade-off for that simplicity is that implementing the API
properly can be quite tricky.

How to do this is a large enough topic that it gets [its own document](https://github.com/facebook/chef-utils/blob/main/Compile-Time-Run-Time.md).
However, some style guidance is also useful. This section assumes you have read
the aforementioned document.

The three main ways that runtime-safety is achieved are `lazy`, `templates`, and
`custom resources`. When should you use which?

The template case is fairly straight forward - if you have a template, read the
node object from the within the template source instead of using `variables`
on the template resource, and all data read is inherently runtime safe since
templates run at runtime.

But what about `lazy` vs `custom resources`? For example, in a recipe you might
do:

```ruby
package 'thingy packages' do
  package_name lazy {
    pkgs = 'thingy'
    if node['fb_thingy']['want_devel']
      pkgs << 'thingy-devel'
    end
    pkgs
  }
  action :upgrade
end
```

Where as inside of a custom resource you could instead do:

```ruby
pkgs = 'thingy'
if node['fb_thingy']['want_devel']
  pkgs << 'thingy-devel'
end

package pkgs do
  action :upgrade
end
```

Which one is better? There's not an exact answer, both work, so it's a style
consideration. In general, there are two times when we suggest a custom
resource:

The first is when you need to loop over the node in order to even know what
resources to create. Since this isn't possible to (well, technically it's
possible with some ugliness, but by and large not using the standard DSL), this
must go into a custom resource. Example might be:

```ruby
# This MUST be inside of a custom resource!
node['fb_thingy']['instances'].each do |name, config|
  template "/etc/thingy/#{instance}.conf" do
    owner 'root'
    group 'root'
    mode '644'
    variables({:config => config})
  end
end
```

The second is when you're using `lazy` on the majority of the resources in
your recipe. If your recipe has 15 resources and you've had to pepper all of
them with `lazy`, it's a bit cleaner to make a custom resource that you call
in your recipe.

It's important here to reiterate: we're **not** referring to using a Custom
Resource as an API, but simply making an internal custom resource, called
only by your own recipe, as a way to simplify runtime safety.

Outside of these two cases, you should default to implementations inside of
recipes. This is for a few reasons.

The first reason is that dropping entire implementations in custom resources
leads to confusion and sets a bad precedent for how runtime-safety works. For
example, consider the custom resource code we saw earlier where you assemble
the package list in "naked" ruby:

```ruby
pkgs = 'thingy'
if node['fb_thingy']['want_devel']
  pkgs << 'thingy-devel'
end
```

This code works fine in a resource, but serves as a bad reference for others -
since this absolutely won't work in a recipe (even though it'll run).

The second reason is that quite often implementations need both compile-time
and runtime code, and by blindly dropping the implementation into a custom
resource, you can often miss this and create bugs like this:

```ruby
# only safe because we're in a custom resource
packages = FB::Thingy.determine_packages(node)

package packages do
  action :upgrade
end

if node['fb_thingy']['want_cron']
  node.default['fb_cron']['jobs']['thingy_runner'] = {
    'time' => '* * * * *',
    'command' => '/usr/bin/thingy --quiet',
  }
end

service 'thingy' do
  action [:enable, :start]
end
```

Note here that while this code all seems reasonable in a custom resource (`if`
statements are runtime safe when inside of a custom resource), that cronjob
will never get picked up, because you're using an API at runtime, but APIs must
be called at compile time and consumed at runtime. In reality, this needs to be
in the recipe in order to work, and should look like this, in a *recipe*:

```ruby
package 'thingy packages' do
  package_name lazy { FB::Thingy.determine_packages(node) }
  action :upgrade
end

node.default['fb_cron']['jobs']['thingy_runner'] = {
  'only_if' => proc { node['fb_thingy']['want_cron'] },
  'time' => '* * * * *',
  'command' => '/usr/bin/thingy --quiet',
}

service 'thingy' do
  action [:enable, :start]
end
```

In general, always start your implementation as a recipe and then escalate to
Custom Resources where necessary.

## Debugging kitchen runs

You can set up kitchen using the same commands as in `.github/workflows/ci.yml`,
but once Chef runs you won't have access to connect, so modify
`fb_sudo/attributes/default.rb` and uncomment the kitchen block.

Then you can do `bundle exec kitchen login <INSTANCE>` after a failed
run, and sudo will be passwordless so you can debug.

## License

See the LICENSE file in this directory

repository: facebook/chef-cookbooks

gha_language: Ruby

repo_name: facebook/chef-cookbooks