text:
---
layout: post
title: Hack The Box - Postman
---

Another [Hack The Box](https://www.hackthebox.eu/) system is in the books!

![1](/images/postman/Title.PNG)

For this Hack The Box (HTB) system, I chose “Postman".  Postman was labeled as “Easy".  Overall, my impression of Postman was positive.  I thought the advertised difficulty was a little off (for me anyway) as there were many things I did not know about the vulnerable application.  Without further delay, let's get root.txt!

## Where To Start
Tackling a HTB machine is always going to be a bit different than a production system at a company or customer location, but the methodology is roughly the same.  While there is some debate over the actual steps, they will typically contain the following phases: Recon, Scanning, Exploitation, and Post-Exploitation.  Some may add in phases like scoping or reporting, or have different names for these phases.

## Scanning
Wait? What happened to the Recon phase?  This is one of those things that is different about a HTB challenge.  Since I already know what my target is, I don't really have to do recon, and can just move into scanning.  If there were an actual company target, or something I would do professionally, then I would be learning as much as possible about the company and their systems minus any actual network or physical interaction with the systems.

### Nmap
Nmap is typically the "go-to" first tool when conducting a pen test or a Capture the Flag (CTF).  Our target has an IP address of <IP_ADDRESS>.  So let's get started…

![1](/images/postman/1.png)

**Image 1** - The Nmap command and preliminary results.

![2](/images/postman/2.png)

**Image 2** - The final Nmap results.

We have several ports open: 22, 80, 6379, and 10000 (as well as several filtered ports).

Port 6379 (Redis) immediately catches my eye and has many known vulnerabilities.  Let’s confirm with telnet that it is indeed Redis.

![3](/images/postman/3.png)

**Image 3** - Using telnet to connect to the Redis server.

In the image above, we ran the “info” command against Redis and confirmed that this is indeed a Redis server.  I found this [site](https://redis.io/commands) to be full of commands that can be run against Redis.

After much trial and error, I found an exploit that is fairly well documented and looks like it will work!

In this exploit, we can overwrite the Private SSH Key that the redis user employs.

This exploit is documented in a few places:
[Packet Storm](https://packetstormsecurity.com/files/134200/Redis-Remote-Command-Execution.html)
[Victor<EMAIL_ADDRESS>[Himanshu Sharma](https://www.google.com/books/edition/Kali_Linux_An_Ethical_Hacker_s_Cookbook/6RhKDwAAQBAJ?hl=en&gbpv=1&bsq=redis&authuser=0)

Let’s walk through this exploit.  First, we need to create our own SSH key pair.

![4](/images/postman/4.png)

**Image 4** - Creating a SSH key pair.

As shown in Image 4, our new keys were created in /root/.ssh.  Let’s move there and take a look at our files.

![5](/images/postman/5.png)

**Image 5** - The newly created SSH key pair.

Per the exploit instuctions, we need to add some “padding” to our public key and we will pipe that to a text file called “temp.txt”

![6](/images/postman/6.png)

**Image 6** - The “padded” temp.txt which contains the public key.

We now have 3 files: our private key, our public key, and the temp.txt file.  Let’s move those to our working directory for everything we are doing with Postman.

![7](/images/postman/7.png)

**Image 7** - The moved files.

## Exploitation

To recap, we have created a SSH key pair and are ready to upload it to the Redis server and overwrite the redis user’s key.

To upload the key, we will cat the temp.txt file and pipe it in a redis-cli command.  If you do not have the redis-cli package, you can install it with “apt-get install redis-tools”.  We can confirm that the key was overwritten by running the “get s-key” command once we have connected to Redis with the redis-cli.

![8](/images/postman/8.png)

**Image 8** - Piping the temp.txt file to overwrite the Redis s-key.

Following the exploit documentation, we will then set the current directory in the redis-cli /var/lib/redis/.ssh.

![9](/images/postman/9.png)

**Image 9** - Setting the directory in the redis-cli.

Following the exploit documentation, we will then set the dbfilename to the authorized_keys file.

![10](/images/postman/10.png)

**Image 10** - Setting the dbfilename in the redis-cli.

We can confirm that the “authorized_keys” file was set properly by running the “CONFIG GET dbfilename” command in the redis-cli.

![11](/images/postman/11.png)

**Image 11** - Confirming the dbfilename in the redis-cli.

Now we need to save our changes in the redis-cli.

![12](/images/postman/12.png)

**Image 12** - Saving the changes in the redis-cli.

Now that our key is written to the server, we will now be able to SSH in as the “redis” user.

![13](/images/postman/13.png)

**Image 13** - SSH’ing (I think that’s a word) in as the “redis” user.

I usually poke around the system for a few basic things: current user, kernel version, etc.  But I am in the system right?  I should be able to (maybe… hopefully…) see the user.txt file and plug that into HTB?

![14](/images/postman/14.png)

**Image 14** - Exploring basic items in the server.

Unfortunately, I could not read the user.txt file.  Looks like I need to become “Matt”.  So let’s do some more exploring.  One of the things to look for are backup files as they can be very fruitful!  And this system is bearing fruit!  We found a id_rsa.bak file which is a backup of a SSH private key.

![15](/images/postman/15.png)

**Image 15** - Locating the backup SSH private key.

We copy the contents of id_rsa.bak into a text editor on our local system.

![16](/images/postman/16.png)

**Image 16** - The copied content of id_rsa.bak.

We will rename the “id_rsa.bak” file to “id_rsa”.  In order to crack this key, we will use John The Ripper.  But first, we need to change the “id_rsa” file into a consumable format for John to use.  To do this we will use the “ssh2john.py” python script already in Kali, and send the output to “crack_me.txt”

![17](/images/postman/17.png)

**Image 17** - Running the ssh2john.py python script.

Let’s check “crack_me.txt”...

![18](/images/postman/18.png)

**Image 18** - The contents of “crack_me.txt”.

Now that we have the SSH private key in a format John can use, it is time to get cracking!

![19](/images/postman/19.png)

**Image 19** - The output of John.

Awesome!  We can see that the password is “postman101”.  Side note: John was taking an eternity to crack this, so on a hunch I did a grep of rockyou.txt for “post” to create a smaller list to try.

Let’s try to SSH in as “matt”.

![20](/images/postman/20.png)

**Image 20** - SSH’ing in as “matt”.

Uh oh!  Looks like “matt” cannot SSH in.  We can confirm this by looking at the “sshd_config” file on the system.  Let’s get back onto the server using method from earlier to gain access as the “redis” user.

![21](/images/postman/21.png)

**Image 21** - The “sshd_config” file is readable.

Scrolling through the “sshd_config” file, we see that Matt is in fact denied SSH access.

![22](/images/postman/22.png)

**Image 22** - The “sshd_config” file.

At this point, I tried to change users in the session I had as “redis” but was being denied with a bad password.  I had to take a step back.  Looking back at the “crack_me.txt file from Image 18, I noticed something interesting.  It looks like this is “sshng” and not ssh!

![23](/images/postman/23.png)

**Image 23** - The contents of “crack_me.txt”.

Digging into this more, there is a [sshng2john.py](https://github.com/stricture/hashstack-server-plugin-jtr/blob/master/scrapers/sshng2john.py) script that can make this consumable for John.  Very sneaky Mr. Postman creator!!!

![24](/images/postman/24.png)

**Image 24** - Downloading the sshng2john.py script.

Next, we will repeat the step from Image 17, but with sshng2john.py.

![25](/images/postman/25.png)

**Image 25** - Running the sshng2john.py python script.

Next, we will repeat the step from Image 19, and hopefully get a good password this time!

![26](/images/postman/26.png)

**Image 26** - The output of John.

Awesome!  We can see that the actual password is “computer2008”.  We can now change users from Redis to Matt with our cracked password.

![27](/images/postman/27.png)

**Image 27** - Changing users from “redis” to “Matt”.

Let’s go through and grab the user.txt file for some HTB glory!

![28](/images/postman/28.png)

**Image 28** - The contents of user.txt.

## Post-Exploitation

Now that we have at least locked down a low privileged user account, we are ready to move on to root!

Looking back at Image 2, we see that port 10000 is open as well and is running Webmin 1.910.  Let’s open up the browser to that and check out what is going on.

![29](/images/postman/29.png)

**Image 29** - The Webmin login page.

Using what we already have, let’s see if Matt and his password work here.

![30](/images/postman/30.png)

**Image 30** - The Webmin login page with Matt’s credentials.

Let’s all let out that collective sigh as we see that Matt’s credentials work and let us into Webmin.  We see that Nmap was correct and that Webmin is at version 1.910.

![31](/images/postman/31.png)

**Image 31** - The Webmin dashboard.

Poking around Webmin did not give me much, I have the ability to do some package updates, but nothing else.  Let’s run this through searchsploit real quick.

![32](/images/postman/32.png)

**Image 32** - The searchsploit results.

What is this?  A package updates vulnerability for version 1.910?  We have to try that out!

Let’s fire up Metasploit (per the results from searchsploit).  I located the exploit needed and loaded it up.  Below are the options I used, being sure to change the “SSL” variable to “true” because Webmin is running on HTTPS (Image 31) and entering in Matt’s credentials.

![33](/images/postman/33.png)

**Image 33** - The Metasploit options.

We run the exploit, become root, and grab the flag!

![34](/images/postman/34.png)

**Image 34** - Victory!

## Reporting
All good penetration tests have one thing in common: good reports.  This is a *very* simplified version of how I would write the Postman findings if I were submitting them.

### Finding 1 - Unauthenticated Redis Server
__Severity__: CVSS v3.1 Vector: AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H - Critical

__Summary__: It was found that the Redis server could be accessed without any authentication.  The assessor was able to access, change, and remove data and files.  It is recommended that Postman administrators employ an authentication mechanism to Redis.

### Finding 2 - Unsecured SSH Private Key
__Severity__: High

__Summary__: It was found that a SSH private key was stored on the system without sufficient protections.  The assessor was able to extract the password from the key and use it in furthering their attacks.  It is recommended that SSH keys be stored in a secure manner.

### Finding 3 - Password Reuse
__Severity__: High

__Summary__: It was found that the “Matt” user had the same password in their SSH key as they did for Webmin access.  The assessor used this access to exploit Webmin and gain root access.  It is recommended that the “Matt” user change both the SSH password and the Webmin password to something unique.

### Finding 4 - Outdated Webmin
__Severity__: CVSS:2.0/AV:N/AC:L/Au:N/C:P/I:P/A:P - High

__Summary__: It was found that the Postman server was using an outdated version of Webmin.  The assessor was able to use a publicly available exploit to gain root access  It is recommended that Postman administrators update Webmin to patch this vulnerability.

### Attack Chain
Nmap scan > port 6379 (Redis) > no authentication on Redis > can overwrite SSH keys for the “redis” user > create “attackers” SSH key > overwrite “redis” key > access the system as “redis” > copied content of id_rsa.bak > extracted password from key > changed to the “Matt” user with extracted password > captured user.txt > accessed Webmin with Matt’s credentials > Metasploit exploit for Webmin 1.910 > root access > captured root.txt

## Conclusion
I hope you enjoyed the write up and the system!  Feel free to reach out to me on [LinkedIn](https://www.linkedin.com/in/aaron-ragusa-3258ba174/) with any questions!


text:
# DesignQL

A self-documenting design system specification for GraphQL.

```gql
query {
  theme {
    colors
    boxShadows
    a11yCombos {
      contrast
      backgroundColor
      color
    }
  }
  component(name: { eq: "Button" }) {
    docs
    propsTable {
      key
      defaultValue
      description
      type {
        name
        description
      }
    }
    styledApi {
      permutations
    }
  }
}
```

## What is it?

DesignQL provides a GraphQL based definition of a design system's primitives that can be queried _and_ written to by all members of a team.
This provides a powerful API for documenting components that still remains flexible for design system teams to have control of design and branding.
It also provides a convenient mechanism for cloning for prototyping one-offs or experimenting with changes to the design system itself (theme, components, etc.).

## Why?

When we build and document design systems we're often forced to reinvent the wheel with bespoke implementations.
There are numerous design system and styleguide tools out there, but they often couple you to custom DSLs or lack flexibility.
DesignQL seeks to provide users with a free and open API to build out design systems and document them with ease.
Tables of props, playgrounds, and much more can be scaffolded out just from the source code and a colocated MDX file.

These days design and development for teams often have numerous render targets.
Keeping them in sync can be difficult, especially when attempting to design generatively, access programmatically, or combine with tools lacking read/write APIs.
Future goals of this project will include outputting a design system's primitives and tokens to React (styled-components/emotion/css modules), Vue, vanilla HTML/CSS (Tachyons, BEM, Tailwind).

We want to share it with the community for a few reasons:

- :family: Improve upon it as a community
- :recycle: Encourage adoption with other design/development tools
- :wrench: Community-based implementations for other libraries/frameworks/etc
- :lock: Avoid lock in for users

## Table of contents

- [Features](#features)
- [How does it work?](#how-does-it-work)
  - [Implementation](#implementation)
  - [Naming conventions](#namingconventions)
- [Specification](#specification)
  - [Types](#types)
    - [DesignSystem](#designsystem)
    - [Component](#component)
    - [Theme](#theme)
    - [Branding](#branding)
    - [StyledFunction](#styledfunction)
    - [Primitives](#primitives)
      - [ColorMap](#colormap)
      - [JSON](#json)

## How does it work?

A design system typically consists of the same key parts:

- :art: theme
- :nail_care: branding
- :ballot_box: components
- :books: documentation
- :trophy: icons

DesignQL boils this down to a schema that can be shared amongst a team and their projects.
It exposes a GraphQL API that can be used to document React code with many CSS-in-JS libraries and down the road export to other render targets like (Atomic CSS, React Native, Vue).

More importantly, it defines and provides an interface for programmatic access mentioned earlier.

### Implementation

DesignQL consists of multiple libraries that handle different types of source files.

Libraries:

- react-docgen
- styled-system
- MDX
- Gatsby

#### Example

Here's an example Button component:

```js
import styled from 'styled-components'
import { color, space } from 'styled-system'
import { variant, size } from './styled-functions'

/* @component */
export const Button = styled.button`
  appearance: button;

  ${color}
  ${space}
  ${variant}
  ${size}
`

Button.displayName = 'Button'

Button.defaultProps = {
  variant: 'primary',
  size: 'md'
}
Button.propTypes = {
  color: color.propTypes,
  variant: variant.propTypes,
  size: size.propTypes,
  ...space.propTypes
}
```

### Naming conventions

In order to keep the MVP as simple as possible, DesignQL currently expects a particular layout structure:

- `src/Button.js`
- `src/Button.mdx`

If there isn't a colocated MDX file it's no problem, DesignQL will do its best to parse out metadata.

### Future

- Source theme data from numerous locations
  - CSS Stats
  - Figma
  - Sketch
  - Framer

## Specification

The DesignQL is defined by the following GraphQL schema:

### Types

The following types are used to define styling, styled functions, components, and theming.

#### DesignSystem

The DesignSystem is the top level type that contains a theme, components, and docs.

```gql
type DesignSystem: {
  theme: Theme!
  branding: Branding!
  components: [Components!]
}
```

#### Component

Components are elements that have a name, props, styling, styled functions and documentation.

```gql
type Component: {
  """
  Name of the component, Pascal cased
  """
  name: String!
  """
  Description of the component
  """
  description: String
  """
  HTML element type, also accepts react native primitive types
  """
  element: String!
  """
  Default props to apply to the component
  """
  defaultProps: JSON
  """
  Property types that the component accepts
  """
  propTypes: JSON
  """
  Property control API of the component, defined as a static property
  """
  propertyControls: JSON
  """
  List of StyledFunctions for the component
  """
  StyledFunctions: [StyledFunction!]
  """
  Additional metadata for the component, including information like status
  """
  metadata: JSON
  """
  Component specific documentation
  """
  docs: String
  """
  Location of the source file on disk
  """
  srcPath: String!
  """
  Location of the MDX file on disk
  """
  docsPath: String
}
```

#### Theme

Themes are objects that define the values used by style props.
Themes ensure consistent margin, padding, colors, font sizes, and other UI constants.

A design system can also define multiple themes.
For example, a team might have a theme for apps and a theme for marketing pages.

```gql
type Theme: {
  """typography"""
  fonts: JSON
  fontSizes: JSON
  fontWeights: JSON
  lineHeights: JSON
  letterSpacings: JSON

  """skins"""
  colors: ColorMap
  shadows: JSON

  """layout"""
  space: JSON
  widths: JSON
  minWidths: JSON
  maxWidths: JSON
  heights: JSON
  minHeights: JSON
  maxHeights: JSON

  """borders"""
  borders: JSON
  radii: JSON

  """variants"""
  variants: JSON

  """media queries"""
  mediaQueries: [String!]
}
```

#### Branding

Branding consists of a brand's primary colors and its logos.
Queries can be made that automatically return the proper logo type and its color based on parameters.

For example, if the background where the logo will be placed is a dark purple, the white logo is returned to ensure proper contrast.

```gql
type Branding {
  """
  List of Logos
  """
  logos: [Logo!]
  """
  Branding specific colors
  """
  colors: ColorMap!
  """
  Documentation for branding
  """
  docs: String
}
```

#### Styled Function

A styled function is based on Styled System.
Styled functions have access to the theme, props, and optionally core Styled System functions.
They return a JSON object.

```gql
type StyledFunction {
  """
  Name for the function
  """
  name: String!
  """
  Component property
  """
  prop: String!
  """
  Name of core styled-system function
  """
  styledSystem: String
  """
  JSON property to set, defaults to prop
  """
  JSONProp: String
  """
  Convert numbers to px values
  """
  toPx: Boolean
  """
  Variant key (for example: buttons)
  """
  variantKey: String
  """
  Does this map to a theme key
  """
  themeKey: String
  """
  Documentation for the function
  """
  docs: String
}
```

### Primitive Types

- ColorMap
- JSON

#### ColorMap

ColorMap consists of an object with nested objects, arrays, and strings.
A color can be represented in hex, rgb, rgba, hsl, or a color name.

Values can only be strings.

Here's an example:

```js
{
  base: 'black',
  bg: 'white',
  blue: '#07c',
  grays: [
    '#999',
    '#555',
    '#111'
  ]
}
```

#### JSON

JSON properties can be an Int, Float, or String so we introduce a `JSONProperty` type.

```js
import { GraphQLJSON } from 'designql'

const typeDef = `
scalar JSON
`

const resolvers = {
  JSON: GraphQLJSON
}
```

## Authors

- John Otander

## License

MIT

license: MIT

repository: UIResources/designql

branch_name: refs/heads/master

extension: md

license_type: permissive

repo_name: UIResources/designql


text:
# IDV with Evident - Configuration Guidelines

## Design
This version of the connector is designed to be engaged in the user self-registration flow of the WSO2 Identity
Server. When a user is registered to IS, we lock the user account and send a verification request to Evident. Then
Evident will send an email to the user with instructions on how to submit the required documents/photos to complete
the verification. Once the user submits data, Evident will process and verify the identity of the user.

![Design Diagram](img/design.png "Design Diagram")

Whenever the user is trying to login to his/her newly created account, WSO2 IS checks with Evident whether the
identity verification has been completed or not, if the user account in the locked state. If the verification is
finished, IS will unlock the user account and let the user login.

## Prerequisites
1. You need to have Evident API credentials for this connector to work. Please
[contact](https://www.evidentid.com/contact-sales/) the Evident team and they will be happy to help.
2. This version of the connector is tested with WSO2 Identity Server version 5.10.0. Make sure to download and set up
the correct version of the [Identity Server](https://wso2.com/identity-and-access-management) on your environment.

## Installing the Connector
1. Download the connector from [WSO2 Connector Store](https://store.wso2.com/store/assets/isconnector/list).
2. Copy the ```org.wso2.carbon.identity.verification.evident.connector-x.x.x.jar``` file to
```<IS-HOME>/repository/components/dropins``` folder.
3. Add the following configurations to the ```<IS-HOME>/repository/conf/deployment.toml``` file.
    ```$xslt
    [[event_handler]]
    name = "evidentEventHandler"
    subscriptions =["POST_ADD_USER", "POST_AUTHENTICATION"]
    ```
4. (Optional Step) For additional debugging purposes, you can enable debug logs for the connector. Add the following
configurations to the ```<IS-HOME>/repository/conf/log4j2.properties``` file.
    ```$xslt
    logger.EVIDENT.name = org.wso2.carbon.identity.verification.evident
    logger.EVIDENT.level = DEBUG
    ```
   Also, make sure to add **EVIDENT** to the **loggers** variable.
   ```$xslt
    loggers = EVIDENT, AUDIT_LOG, trace-messages...
   ```
4. Restart the server.

## Configuration Steps
1. Log in to the Identity Server management console using your admin credentials. (Default credential:
```admin:admin```)
2. Click **Add** under **Claims** section and click on **Add Local Claim** option.
3. Provide the following details and click on **Add** to create a new local claim.
    - Claim URI: http://wso2.org/claims/identity/evidentRequestID
    - Display Name: Evident Request ID
    - Description: Evident Request ID
    - Mapped Attribute (s)
        - PRIMARY - evidentRequestID
    - Check _Supported by Default_ option.
    ![Add Evident ID Claim](img/add-evident-id-claim.png "Add Evident ID Claim")
4. Click on **Resident** under **Identity Providers** section.
5. Expand the **Account Management Policies** and a new section named **Evident Identity Verification** should be
 present.
6. Expand the section and provide below configurations.
    - Enable Identity Verification: Check the checkbox to enable the connector.
    - API Base Path: Specify the Evident API base path. Check
    [Evident API documentation](https://www.evidentid.com/api-documentation-developers/) for more info.
    - API Key: Add the API key (username) obtained from Evident.
    - API Secret: Add the API secret obtained from Evident.
    - Verification Email Summary: This is the summary of the email that will be sent to the user by Evident. The value
    will be appended to the default text. Ex: **Action Required to Complete Your [Summary]**.
    - Verification Email Description: This will appear in the verification email as the description.
    - Verify Enabled User Stores: If you have multiple user stores, you can specify to which user stores that you'd
    need to enable the verification. Comma separated multiple values are accepted an if kept empty, verification will
    be applied to all the user stores.
    ![Configure Evident Connector](img/configure-evident-connector-settings.png "Configure Evident Connector")
7. Since the identity verification is engaged in user self-registration, we need to enable that too. Expand the
**User Self Registration** section and check **Enable Self User Registration** checkbox. Make sure that the
**Internal Notification Management** is not checked since Evident is handling the notification sending.
8. Click on **Update** to save the configurations.

## Testing
1. Visit the [WSO2 Identity Server User-Portal](https://localhost:9443/user-portal/) and in the Sign In page,
click on **Create Account** to register a new user.
2. Complete the form and click on the register button. Make sure to enter a valid email address that you have access to.
3. Try to login to the newly created user account. The server should say that the account is not verified yet.
3. Check the inbox for a verification request email from Evident, that'd look like below.
    ![Evident verification email](img/evident-idv-mail.png "Evident verification email")
4. Complete the verification by clicking on the **Begin Now** button in the email and following the instructions
provided.
    - This version of the connector checks the validity of the US Driver's License of the user, and the First Name and
     Last Name extracted from the Driver's License should match with the provided first name and last name when
     self registering.
    - Please note that you'll need to have a valid US Driver's License for successful verification. You can
    manually complete the verification for testing purposes, through Evident API, using the **userIdentityToken**
    returned. This is printed in WSO2 Identity Server logs if debug logs are enabled for the connector.

## Limitations
1. This version of the connector doesn't have an option to customise the verification attributes of the request. By
 default, it sends verification requests for ```core.fullname``` and
 ```identity_assurance.document_verification.americas.us.drivers_license``` attributes. Please visit
[Evident documentation](https://www.evidentid.com/api-documentation-developers) for more information on these
attributes.


text:
---
author: admin
comments: true
date: 2010-07-25 09:26:46+00:00
layout: post
slug: how-it-was-done-nigerian-postcode-data-extraction
title: How it was done - Nigerian postcode data extraction
wordpress_id: 99
categories:
- Open Data
- Programming
tags:
- Nigeria
- postcodes
- python
- scraping
---

In my previous post, I talked about open data and how making the Nigerian postcode data open and more accessible has a wide potential for powering several applications. I've received several comments on Facebook with even more examples on how that data could be useful.

In this post, I would share how this extraction was done and how similar extraction scripts or scrapers could be written.

The first step in every scraping project I begin is to understand the HTTP dialog for the website I want to scrape. So I attempt to answer questions like these:

  1. Does the application need me to login?

  2. Is it sensitive to certain HTTP features like cookies or referrers?

  3. What urls do I access to view the content I want to extract?

  4. What variables can I set to change the view and specify what I want?

Determining the answers to these questions can be obtained by using tools that enable you view this dialog. I personally like to use [Firebug](http://getfirebug.com/) for this task.

[caption id="attachment_100" align="alignnone" width="300" caption="Click for a larger version"][![HTTP Dialog](/public/uploads/2010/07/http-dialog-nigeriapostcodes.com_-300x203.png)](/public/uploads/2010/07/http-dialog-nigeriapostcodes.com_-e1280048721758.png)[/caption]

After you've determined the HTTP dialog, you can then write your script to do the extraction. You can write scrapers in any language provided it has support to retrieve HTTP resources and parse HTML. The parsing aspect of a scraper is usually the most interesting part because a lot of parsing libraries choke when they encounter badly formed HTML.

In the code snippet below, I used [BeautifulSoup](http://www.crummy.com/software/BeautifulSoup/) for parsing the HTML and python's [urllib2](http://docs.python.org/library/urllib2.html) for the HTTP communication.

The code is [available on Github](http://gist.github.com/484852) and although it changes as more functionality is added, you can view the revision log of the gist to see the history of changes.

extension: markdown

gha_language: HTML


text:
# Remote Garage

## Company blurb

[Remote Garage](http://www.remotegarage.club/) is on a mission to bring out your full potential as a full-stack Go programmer.  Come join us!

We are a community of gophers, who do programming not because we expect to get paid or get adulation from the public, but because it is fun to program.

## Company size

~10 employees (as of Aug 2020).

## Remote status

We highly believe in and focus on providing remote employment.

## Region

India

## Company technologies

Docker, Kubernetes, React, Golang, GRPC, JavaScript.

## Office locations

The main offices are located in Bangalore.

## How to apply

Visit our [Contact Page](https://angel.co/company/remotegarage)

repository: remoteintech/remote-jobs

branch_name: refs/heads/main

gha_language: JavaScript

repo_name: remoteintech/remote-jobs


text:
* [How to use functions](#how-to-use-functions)
* [String functions](#string-functions)
* [Aggregating functions](#aggregating-functions)
* [Custom functions](#custom-functions)

## How to use functions
In cases when you want to retrieve function result from a query you have to declare function as a variable like:
```kotlin
val lowerCasedName = FooTable.name.lowerCase()
val lowerCasedNames = FooTable.slice(lowerCasedName).selecAll().map { it[lowerCasedName] }

```
Also, functions could be chained and combined:
```kotlin
val trimmedAndLoweredFullName = Concat(FooTable.firstName, stringLiteral(" "), FooTable.lastName).trim().lowerCase()
val fullNames = FooTable.slice(trimmedAndLoweredFullName).selecAll().map { it[trimmedAndLoweredFullName] }

```

## String functions
### LowerCase/UpperCase
Returns lower-cased/upper-cased string value.
```kotlin
val lowerCasedName = FooTable.name.lowerCase()
val lowerCasedNames = FooTable.slice(lowerCasedName).selecAll().map { it[lowerCasedName] }

```

## Aggregating functions
Those functions should be used in queries with [[groupBy|DSL#group-by]].
### Min/Max/Average
Returns minimum/maximum/average value, could be applied to any comparable expression
```kotlin
val minId = FooTable.id.min()
val maxId = FooTable.id.max()
val averageId = FooTable.id.avg()
val (min, max, avg) = FooTable.slice(minId, maxId, averageId).selecAll().map {
    Triple(it[minId], it[maxId], it[averageId])
}

```

## Custom functions
If you can't find your most loved function used in your database (as Exposed provides only basic support for classic SQL functions) you can define your own functions.

Since Exposed 0.15.1 there multiple options to define custom functions:
1. Function without parameters:
```kotlin
val sqrt = FooTable.id.function("SQRT")
```
In SQL representation it will be `SQRT(FooTable.id)`

2. Function with additional parameters:
```kotlin
val replacedName = CustomFunction<String?>("REPLACE", VarCharColumnType(), FooTable.name, stringParam("foo"), stringParam("bar"))

```
`CustomFunction` class accept function name as a first parameter and resulting column type as second, after that you can provide any amount of parameters with will be separated by a comma.

There are also shortcuts for string, long and datetime functions:
* `CustomStringFunction`
* `CustomLongFunction`
* `CustomDateTimeFunction`

The code above could be simplified to:
```kotlin
val replacedName = CustomStringFunction("REPLACE", FooTable.name, stringParam("foo"), stringParam("bar"))

```

repository: Tapac/exposed-wiki

repo_name: Tapac/exposed-wiki


text:
![](https://img.shields.io/badge/Microverse-blueviolet) [![Hits](https://hits.seeyoufarm.com/api/count/incr/badge.svg?url=https%3A%2F%2Fgithub.com%2Flfmnovaes%2Ftodo-list&count_bg=%2379C83D&title_bg=%23555555&icon=&icon_color=%23E7E7E7&title=hits&edge_flat=false)](https://hits.seeyoufarm.com)

# LeaderBoard

> The leaderboard website displays scores submitted by different players. It also allows you to submit your score. All data is preserved thanks to the external Leaderboard API service.

## Preview

![image](preview.png)

## Live Demo

[Live Demo Link](https://iammouaz.github.io/leaderboard)

## Built With

- HTML & CSS
- Javascript
- Webpack

## Getting Started

- Run git clone on this project at the desired directory:
   ```
   git clone https://github.com/iammouaz/leaderboard.git
   ```
- Run `npm install` to install the necessary packages to run locally
- After installing everything, run `npm start` and your default browser will open with the page

### Prerequisites

An updated web browser

### Usage

- Type the score and your name in the text field and submit
- Watch your score on the list and check who is better.

## Authors

👤 **Mouaz El Molkey**

- GitHub: [![@iammouaz](https://img.shields.io/github/watchers/iammouaz/portfolio?color=lightgray&style=plastic&labelColor=blue)](https://github.com/iammouaz)
- Twitter: [![@iammouaz](https://img.shields.io/twitter/follow/iammouaz?style=plastic&labelColor=blue)](https://www.twitter.com/MoazMulki1/)
- LinkedIn: [![@liammouaz](https://img.shields.io/badge/LinkedIn-blue?style=plastic&logo=linkedin)](https://www.linkedin.com/in/mohammad-mouaz-molki-1368981bb/)

## 🤝 Contributing

Contributions, issues, and feature requests are welcome!

Feel free to check the [issues page](../../issues/).

## Show your support

Give a ⭐ if you like this project!

## Acknowledgments

To everyone in Microverse.

## 📝 License

This project is [MIT](./LICENSE) licensed.

repository: iammouaz/leaderboard

branch_name: refs/heads/dev

repo_name: iammouaz/leaderboard


text:
# DynastyDashboard

App URL: https://dynastydashboard.netlify.app/#/

### Pre installations:
Install Grunt CLI: npm install -g grunt-cli
Install Netlify CLI: npm install netlify-cli -g
npm install

### Run Locally:
grunt default
netlify dev

MFL Doc: https://www63.myfantasyleague.com/2021/api_info?STATE=test&CCAT=export&TYPE=players&L=24385

### BUGS:
* Projected Scores when not logged in

### MAJOR FEATURES:
* Draft
* Lineup

### SMALL ENHANCEMENTS
* Encrypt Cookies and un-encrypt in function
* Tagging of players with 1:many tags
* More data
** Roster vs IR spot: https://www63.myfantasyleague.com/2021/export?TYPE=rosters&L=24385&APIKEY=&FRANCHISE=&W=&JSON=1
** Matchup/Schedule: https://api.myfantasyleague.com/2021/export?TYPE=nflSchedule&W=&JSON=1
** BYE Week: https://api.myfantasyleague.com/2021/export?TYPE=nflByeWeeks&W=&JSON=1
* Other Rankings Sources
** Weekly
** Rest of Season
** Dynasty

repository: badamowski/DynastyDashboard

gha_license_id: MIT

repo_name: badamowski/DynastyDashboard


text:
---
description: 'First-In, First-Out'
---

# FIFO

The first type of jobs we are going to describe is the FIFO \(First-In, First-Out\) type. This is the standard type when adding jobs to a queue. The jobs are processed in the order they are inserted into the queue. This order is preserved independently on the amount of processors you have, however if you have more than one worker or concurrency larger than 1, even though the workers will start the jobs in order, they may be completed in a slightly different order, since some jobs may take more time to complete than others.

```typescript
import { Queue } from 'bullmq'

const myQueue = new Queue('Paint');

// Add a job that will be processed after all others
await myQueue.add('wall', { color: 'pink' });
```

When you add jobs to the queue there are several options that you can use. For example you can specify how many jobs you want to keep when the jobs are completed or failed:

```typescript
await myQueue.add(
  'wall',
  { color: 'pink' },
  { removeOnComplete: true, removeOnFail: 1000 },
);
```

In the example above all completed jobs will be removed automatically and the last 1000 failed will be kept in the queue.

## Default job options

Quite often you will want to provide the same job options to all the jobs that you add to the Queue. In this case you can use the "defaultJobOptions" option when instantiating the Queue class:

```typescript
const queue = new Queue('Paint', { defaultJobOptions: {
  removeOnComplete: true, removeOnFail: 1000
});
```


text:
---
id: first_multiplayer_game
name: My First Multiplayer Game
title: My First Multiplayer Game
tags:
    - Tutorial
---

# Build Your First Game In Core

<lite-youtube videoid="-rIbd612sUM" playlabel="Build Your First Game In Core"></lite-youtube>
{: .video-container }

## Overview

Jump in and build a game using Core's Deathmatch framework. Customize as much or as little as you want to build this multiplayer arena shooter.

- **Completion Time:** 10 minutes.
- **Previous Knowledge:** [Installing Core](installing_core.md).
- **Skills you will learn:**
    - Core Frameworks
    - Core Content
    - Manipulating Objects
    - Applying Materials
    - Collision
    - Player Settings
    - Game Settings
    - Spawn Points

## Start a New Project

To get started, use the **Create** menu to make a new project

### Click **Create New**

![Create New](../img/MyFirstMultiplayer/CreateNew.png){: .center loading="lazy" }

1. With Core open, click the **Create** Tab on the left side menu.
2. Click **Create New Game**.

### Select the **Deathmatch** framework

![Deathmatch](../img/MyFirstMultiplayer/Deathmatch.png){: .center loading="lazy" }

1. Click **View Frameworks** in the **Core Game Frameworks** option.
2. Click **Deathmatch**.
3. Name your project. `MyFirstGame` works well, but choose any name.
4. Click **Create**.

## Explore the Project

The Deathmatch framework gives you a complete game arena and shooter functionality out of the box.

![Whitebox](../img/MyFirstMultiplayer/WhiteboxMapMarked.jpg){: .center loading="lazy" }

### Test Player Movement

- Press ![Play](../img/EditorManual/icons/Icon_Play.png) or ++equal++ to preview your project as a player.
{: .image-inline-text .image-background }
- Press ++tab++ to pause the preview.
- Press ![Stop](../img/EditorManual/icons/Icon_Stop.png) or ++equal++ to stop the preview.
{: .image-inline-text .image-background }

As in any Core game project, you already have a working character controller.

- Move the character with the ++W++, ++A++, ++S++, and ++D++ keys.
- Jump with ++Space++.
- Crouch with ++C++.
- Ride a mount with ++G++.

### Test Shooter Mechanics

Besides player movement, **Deathmatch** also gives each player a gun to shoot, and the ability to open and close doors.

- Shoot the default gun with the left mouse button.
- Open and close a door with ++F++.

![PlayMode](../img/MyFirstMultiplayer/PlayMode.jpg){: .center loading="lazy" }

### Test Multiplayer Gameplay

Core projects also include multiplayer networking by default. Because this is a crucial component of this game, it is important to test using **Multiplayer Preview Mode** as much as possible.
![TwoPlayers](../img/MyFirstMultiplayer/TwoPlayers.png){: .center loading="lazy" }

1. Click ![Multiplayer Preview Mode](../img/EditorManual/icons/Icon_MultiplayerTest.png) to switch the Preview Mode to Multiplayer.
    {: .image-inline-text .image-background }

2. Press ![Play](../img/EditorManual/icons/Icon_Play.png) to start the preview. This will open a separate game window for each player.
    {: .image-inline-text .image-background }

    ![MPPreview](../img/MyFirstMultiplayer/MultiplayerPreviewPlay.png){: .center loading="lazy" }

!!! tip
     You can use ++Alt+enter++ to toggle between fullscreen and windowed mode. You can also use ++Win+Arrow++ to dock the screens side by side.

## Customize the Arena

### Explore Core Content

Core gives you a massive library of 3D assets, materials, sounds, and components for making games, which can be found in the **Core Content** Window.

!!! note
    You can reopen the **Core Content** window by going to **Window** > **Core Content** in the top menu bar.

1. Click **Core Content**.
2. Drop down the **3D Objects** menu to see the props and objects that can be added to the scene.
3. Click on the **Nature** subcategory.
4. Choose a bush and some other props to drag into the scene.

    <video autoplay loop muted playsinline poster="/img/EditorManual/Abilities/Gem.png">
        <source src="/img/MyFirstMultiplayer/DragDropBushes.webm" type="video/webm" />
        <source src="/img/MyFirstMultiplayer/DragDropBushes.mp4" type="video/mp4" />
    </video>

### Create Hiding Places

You can move, turn, and resize objects.

- ![Transform Position](../img/EditorManual/icons/Icon_TransformPosition.png) or ++W++ activates Translation Mode.
{: .image-inline-text .image-background }
- ![Rotate Tool](../img/EditorManual/icons/Icon_TransformRotation.png) or ++E++ activates Rotation Mode.
{: .image-inline-text .image-background }
- ![Snap Position](../img/EditorManual/icons/Icon_TransformScale.png) or ++R++ activates Scale Mode.
{: .image-inline-text .image-background }

    <video autoplay loop muted playsinline poster="/img/EditorManual/Abilities/Gem.png">
        <source src="/img/MyFirstMultiplayer/MoveBushes.webm" type="video/webm" />
        <source src="/img/MyFirstMultiplayer/MoveBushes.mp4" type="video/mp4" />
    </video>

1. Click on the bush and press ++G++ to move it.
2. Use the arrows to move it into a good hiding place for a player.
3. Press ++R++ to change the size of the bush.
4. Click and drag the white box at the center of the bush to resize it proportionately.
5. Move, rotate, and scale the rest of the objects to enhance the scene.

### Turn Off Collision

By default, Core objects have collision, so players can't just walk into bushes yet.

1. Test this by pressing ![Play](../img/EditorManual/icons/Icon_Play.png) to preview the game.
{: .image-inline-text .image-background }
2. Look at your props from a player perspective. You should be able to walk up to a bush, but collide with it once you touch it.
3. Click on the bush to select it, and open the **Properties** window.
4. Find the **Collision** property and change it to **Force Off**.

    <video autoplay loop muted playsinline poster="/img/EditorManual/Abilities/Gem.png">
        <source src="/img/MyFirstMultiplayer/NoCollisonBush.webm" type="video/webm" />
        <source src="/img/MyFirstMultiplayer/NoCollisonBush.mp4" type="video/mp4" />
    </video>

You should now be able to walk into a bush. Test this in **Multiplayer Preview Mode** to see how well it works for concealment.

!!! note
    You can reopen the **Properties** window by going to **Window** > **Properties** in the top menu bar.

## Finishing the Arena

### Add a Material to an Object

**Materials** allow you to add colors and textures to the objects in the scene, by dragging and dropping them onto objects.

1. In the **Core Content** window, drop down the **Materials** menu to see the options.
2. Pick a material, and drag it onto one of the objects in the scene.

    <video autoplay loop muted playsinline poster="/img/EditorManual/Abilities/Gem.png">
        <source src="/img/MyFirstMultiplayer/MaterialExample.webm" type="video/webm" />
        <source src="/img/MyFirstMultiplayer/MaterialExample.mp4" type="video/mp4" />
    </video>

### Cover the Walls

You can apply a material to multiple objects by selecting them.

- Use ++shift+Left Click++ to select more objects.
- Left click and drag to select objects in an area.

    <video autoplay loop muted playsinline poster="/img/EditorManual/Abilities/Gem.png">
        <source src="/img/MyFirstMultiplayer/WoodWalls.webm" type="video/webm" />
        <source src="/img/MyFirstMultiplayer/WoodWalls.mp4" type="video/mp4" />
    </video>

1. In the **Hierarchy** window, type "wall" into the search bar to show only the objects named **Whitebod Wall 01**.
2. Press ++enter++ to select everything from the search.
3. Choose a material, and drag it onto one of the walls.

!!! note
    You can also select the entire list by clicking the first object in the list, then holding ++shift++ and scroll down to click the last.

### Give Everything a Material

You can continue using these techniques to complete the appearance of your Deathmatch arena. Try searching for each of these labels to apply materials in groups:

- `stairs`
- `window insert`
- `floor`

![FinishArt](../img/MyFirstMultiplayer/FinishArt.jpg){: .center loading="lazy" }

!!! info
    You can customize materials and how they apply to objects. Learn more in the [Custom Material Tutorial](custom_materials.md).

## Customizing Gameplay

In this final section, you will find different ways to change the gameplay itself.

### Add Double Jumping

![PlayerSettings](../img/MyFirstMultiplayer/PlayerSettings.png){: .center loading="lazy" }

1. Find **Player Settings** by searching for it in the **Hierarchy**.
2. Open the **Properties** window to see all the settings that can be changed for each player
3. In the **Jump** section, change **Jump Max Count** to `2`,
4. Press ![Play](../img/EditorManual/icons/Icon_Play.png) to test out double-jumping with ++Space++.
{: .image-inline-text .image-background }

![DoubleJump](../img/MyFirstMultiplayer/DoubleJump.png){: .center loading="lazy" }

### Change The Round Kill Limit

In the top left corner of the screen in game, you can see that you win the Deathmatch by killing 10 opponents. This can be changed in **Game Settings**.

![RoundKillLimit](../img/MyFirstMultiplayer/RoundKillLimit.png){: .center loading="lazy" }

1. Search for **Round Kill Limit** in the **Hierarchy**.
2. Open the **Properties** window.
3. Find the **KillLimit** property and change it to `2`.
4. Start a **Multiplayer Preview** of your game, and see if you win by shooting an opponent twice.
{: .image-inline-text .image-background }

![ChangedKillLimit](../img/MyFirstMultiplayer/ChangedKillLimit.png){: .center loading="lazy" }

### Change the UI Instructions

Although the game now ends after two kills, the instructions shown on the screen still tell players to shoot for ten.

1. Search for **UI Text Box** under **Game Instructions** in the **Hierarchy**.
2. Open the **Properties** window.
3. Change the **Text** property to match your game's win condition.

![ChangedGameInstructions](../img/MyFirstMultiplayer/ChangedGameInstructions.png){: .center loading="lazy" }

### Move the Player Start

Let's move the "Player Start" where players spawn to be further apart. Press ++V++ to toggle gizmo visibility -- you can now see the camera, spawn points, and trigger boxes.

1. Search for **Spawn Point** in the **Hierarchy**.
2. Move the spawn points around the map the same way you would any object.

![PlayerSpawn](../img/MyFirstMultiplayer/PlayerSpawn.jpg){: .center loading="lazy" }

!!! tip
    Press ++0++ to create a spawn point at your cursor's location. There are more [Editor Shortcuts](editor_keybindings.md) that can streamline your game creation flow.

## Publishing a Game

You now have a complete and unique deathmatch-style game. If you are ready to test it with real human players, then [publish your game](publishing.md).

## Next Steps

[Publish a Game](publishing.md) | [Terrain Tutorial](environment_art.md) | [Basic Weapon Tutorial](weapons.md) | [Abilities Tutorial](ability_tutorial.md)

repository: PopThosePringles/platform-documentation

branch_name: refs/heads/development

repo_name: PopThosePringles/platform-documentation


text:
# bitrise_bcsymbolmaps plugin

[![fastlane Plugin Badge](https://rawcdn.githack.com/fastlane/fastlane/master/fastlane/assets/plugin-badge.svg)](https://rubygems.org/gems/fastlane-plugin-bitrise_bcsymbolmaps)

## Getting Started

This project is a [_fastlane_](https://github.com/fastlane/fastlane) plugin. To get started with `fastlane-plugin-bitrise_bcsymbolmaps`, add it to your project by running:

```bash
fastlane add_plugin bitrise_bcsymbolmaps
```

## About bitrise_bcsymbolmaps

Download BCSymbolMaps from Bitrise before uploading them to a crash reporting tool.

## Example

Check out the [example `Fastfile`](fastlane/Fastfile) to see how to use this plugin. Try it by cloning the repo, running `fastlane install_plugins`.

In order to download bitcode symbol maps, provide a Personal Access Token from Bitrise as well as a app slug (last segment of the app URL).
We're assuming that release builds are coming from `release/*` branches (thanks to [Gitflow](https://nvie.com/posts/a-successful-git-branching-model/)) and we only need successful builds (`status: "1"`).

```ruby
build = bitrise_download_bcsymbolmaps(
  api_access_token: ENV["BITRISE_TOKEN"],
  app_slug: ENV["BITRISE_APP_SLUG"],
  branch: "release/#{version}",
  status: "1"
)
```

This will return an object with two attributes: `build_number` and `commit_hash`. Having this information is sufficient to [download dSYMs from AppStore Connect](fastlane/Fastfile#L23-L27) and [create a release on Bugsnag](fastlane/Fastfile#L29-L34).

After all the operations are done, you might want to cleanup a work directory.

```ruby
bitrise_clean_bcsymbolmaps
```

## Issues and Feedback

For any other issues and feedback about this plugin, please submit it to this repository.

## Troubleshooting

If you have trouble using plugins, check out the [Plugins Troubleshooting](https://docs.fastlane.tools/plugins/plugins-troubleshooting/) guide.

## Using _fastlane_ Plugins

For more information about how the `fastlane` plugin system works, check out the [Plugins documentation](https://docs.fastlane.tools/plugins/create-plugin/).

## About _fastlane_

_fastlane_ is the easiest way to automate beta deployments and releases for your iOS and Android apps. To learn more, check out [fastlane.tools](https://fastlane.tools).


text:
# govaccine :syringe:

`govaccine` is a small project I developed in just a few hours **to monitor and automatically book appointment slots for COVID-19 shots** (both first shot and booster shot) in France :fr:.
It works with the online appointment platform [Doctolib](https://www.doctolib.fr).

To comply with government rules, **it only looks for "_chronodoses_"** :stopwatch:, i.e. appointment slots which haven't been booked (or have been freed) less than 24 hours prior to the appointment. These _chronodoses_ are **allowed for all people above 18**, unlike other shots.

Only _Pfizer-BioNTech_ and _Moderna_ vaccines are allowed for chronodoses and the algorithm actually **only checks for Pfizer-BioNTech** at this time (Pfizer-BioNTech is the most widespread in Paris vaccination centers currently, I didn't take time to make it work with Moderna).

`govaccine` is much faster :rocket: than browser-based solutions (browser extensions, web automation tools like Selenium, etc.) because it's **100% headless**: there is no interaction with external systems other than Doctolib's API.

The program is **working as of May 26th 2021**, however changes to the Doctolib API or content might break it.

## Usage :open_book:

First, you need to create a text file containing all the Doctolib URLs of the vaccination centers you're interested in, **one URL per line**.
You can find these URLs by searching for vaccination centers on the Doctolib website and copying the URl shown in your browser.
Example:
```text
https://www.doctolib.fr/vaccination-covid-19/paris/centre-de-vaccination-covid-paris-15e
https://www.doctolib.fr/vaccination-covid-19/paris/centre-de-vaccination-cpam-de-paris
https://www.doctolib.fr/vaccination-covid-19/paris/centre-de-vaccination-paris-14e
```
A file is already provided with all Paris vaccination centers in `./assets/paris_vaccination_centers.txt`. You can use it if you want to get vaccinated in Paris. You will need to create your own text file for other places, as explained above.

Then, run the program: `./govaccine -u EMAIL -p PASSWORD -f PATH_TO_YOUR_VACCINATION_CENTERS_TEXTFILE`

The program will exit once an appointment has been booked.

Full usage:
```text
Usage of govaccine:
  -f string
        Filepath of a file containing the URLs of the desired vaccination centers (1 URL per line)
  -p string
        Doctolib password
  -s uint
        Number of seconds between each appointment check for a single worker (default 1)
  -t uint
        Number of seconds after which a request times out (default 5)
  -u string
        Doctolib username (email)
  -w uint
        Number of workers checking for appointments concurrently (default 4)
```

## Personal data :memo:

The program only communicates with `doctolib.fr` in HTTPS (HTTP Secure). No data is sent anywhere else and no data is stored by the program.

## Technical details :desktop_computer:

As its name suggests, `govaccine` is written in Go... solely because I wanted to practice Go (so the code might not be very idiomatic).

To compile the program, go to the `./cmd/govaccine/` directory and execute `go build .` This will create the `govaccine` executable file which you can run as explained above.

## Known issues :bug:

### Unconfirmed appointment

`govaccine` assumes the appointment is confirmed and exits as long as it issued the _request_ to confirm the appointment (without actually checking the _response_ of the request).

If someone else is booking the same appointment and confirms it first, this will cause `govaccine` to believe you got the appointment and exit (while in fact the appointment was given to someone else).

**The workaround is simply to re-run `govaccine` to book another appointment.**

This issue hasn't been fixed yet because one needs to know the response returned by the API in the case described above, which is not easy to reproduce.

repository: GuiTeK/govaccine

repo_name: GuiTeK/govaccine


text:
# discordVoIP
[![forthebadge made-with-python](http://ForTheBadge.com/images/badges/made-with-python.svg)](https://www.python.org/)

[![ForTheBadge built-with-love](http://ForTheBadge.com/images/badges/built-with-love.svg)]()

[![GitHub issues](https://img.shields.io/github/issues/Pitu7944/discordVoIP?style=for-the-badge)](https://github.com/Pitu7944/discordVoIP/issues)

**discordVoIP** is a **FiveM** script for using discord as voice in radios, phones and more.
It provides a simple api for adding job restricted channels, and more.
Click the **wiki** button for documentation <3

## Installation
*Python Part*
```bash
sudo apt update
sudo apt install software-properties-common
sudo add-apt-repository ppa:deadsnakes/ppa # When prompted press Enter to continue
sudo apt install python3.8 python3-venv tmux
mkdir ~/discordVoIP_Server
cd ~/discordVoIP_Server
git clone "https://github.com/Pitu7944/discordVoIP.git" ./
python3.8 -m venv env
```
*FiveM Part*
```
Move the discordVoIP folder to your fivem resources folder
add start discordVoIP to your server cfg and configure values in server.lua!
```

## Usage

```bash
source ~/discordVoIP_Server/env/bin/activate
# right here you want to go to config.py and edit the fields according to the comments included in the file
tmux new-session -d -s discordVoIP_discordModule "python3.8 ~/discordVoIP_Server/discord_module.py"
tmux new-session -d -s discordVoIP_requestHandler "
python3.8 ~/discordVoIP_Server/requesthandler_module.py"
```

## Contributing
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.

Please make sure to update tests as appropriate.

## License
[![MIT license](https://img.shields.io/badge/License-MIT-blue.svg)](https://lbesson.mit-license.org/)

repository: bgtracker/discordVoIP

repo_name: bgtracker/discordVoIP


text:
# Service-oriented Computing - Assignment 1

## Simple Node.js Server Application

The simple Node.js server application used in this exercise is found inside the [nodejs-server](./nodejs-server) directory.

### Prerequisits

1. Ensure that [Node.js is installed](https://nodejs.org/en/download/)
2. (Recommended) [Visual Studio Code] (https://code.visualstudio.com/) is an extensible code editor that will help you work on small applications like this one.
3.
4. The application runs on port `3000`, so ensure it is free.

### How to start the server application (Windows)?

1. Open `Git Bash` in an empty directory.
2. Clone the repository locally: `git clone https://github.com/iaas-exercises/soc-assignment-1.git .`.
3. Open the respective code directory: `cd ./nodejs-server`.
4. Install dependencies: `npm install`.
5. Start the application: `npm start`.
6. You can stop the application by opening cmd or powershell and using the following command `taskkill /im node.exe /F`

### Exposed endpoints

- `http://<IP_ADDRESS>:3000/shopping-cart`
- `http://<IP_ADDRESS>:3000/shopping-cart/{id}`
- `http://<IP_ADDRESS>:3000/wisdom`
- `http://<IP_ADDRESS>:3000/login`


text:
# yeh
a poorly named helm chart wrapping https://github.com/rakyll/hey

## quickstart
(assuming your cwd is the root of this repo)
1. Build the image (`docker build -t (your-registry)/hey:(some tag) docker/`)
2. Spin up a cluster with k3d or kind (briefly tested with both)
3. Create a snippet of yaml to feed in with `helm install -f (some file).yaml` overriding `HEY_TARGET`
3. `helm install -n (desired namespace) yeh chart/`

Most flags are represented as environment variables in `chart/values.yaml`, please understand
yes that is case sensitive (this chart is hacky and that was generated with some janky tooling I wrote a few weeks ago)

repository: MylesBock/yeh

repo_name: MylesBock/yeh


text:
# Change Log

All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.

## [1.2.4](https://github.com/cultureamp/kaizen-design-system/compare/@kaizen/draft-card@1.2.3<EMAIL_ADDRESS>(2020-09-28)

**Note:** Version bump only for package @kaizen/draft-card

## [1.2.3](https://github.com/cultureamp/kaizen-design-system/compare/@kaizen/draft-card@1.2.2<EMAIL_ADDRESS>(2020-09-24)

### Bug Fixes

* Change styles from require to use import ([#782](https://github.com/cultureamp/kaizen-design-system/issues/782)) ([defd448](https://github.com/cultureamp/kaizen-design-system/commit/defd4483faa3459d9af48e272c63656798008a28))

## [1.2.2](https://github.com/cultureamp/kaizen-design-system/compare/@kaizen/draft-card@1.2.1<EMAIL_ADDRESS>(2020-09-08)

### Bug Fixes

* expose public function in draft card ([#771](https://github.com/cultureamp/kaizen-design-system/issues/771)) ([b8007ae](https://github.com/cultureamp/kaizen-design-system/commit/b8007ae9712d3dc94b971ba22fc1cb1cd29ce39f))

## [1.2.1](https://github.com/cultureamp/kaizen-design-system/compare/@kaizen/draft-card@1.2.0<EMAIL_ADDRESS>(2020-09-07)

### Bug Fixes

* Bump design-tokens peer dependency to the latest version ([#760](https://github.com/cultureamp/kaizen-design-system/issues/760)) ([37e5414](https://github.com/cultureamp/kaizen-design-system/commit/37e5414b2e2c0befb4127c588120eb2e8bdc4d39))

# [1.2.0](https://github.com/cultureamp/kaizen-design-system/compare/@kaizen/draft-card@1.1.0<EMAIL_ADDRESS>(2020-08-05)

### Features

* add card for Elm ([#690](https://github.com/cultureamp/kaizen-design-system/issues/690)) ([b3054bd](https://github.com/cultureamp/kaizen-design-system/commit/b3054bd5d208854c7fb2c2454cefc3968071cfcf))

# 1.1.0 (2020-07-02)

### Features

* Added card package ([#594](https://github.com/cultureamp/kaizen-design-system/issues/594)) ([e561f5e](https://github.com/cultureamp/kaizen-design-system/commit/e561f5e824809405dc22f6609f1d3eaf0040ad94))

repository: keberox/kaizen-design-system

repo_name: keberox/kaizen-design-system


text:
bootstrap-radio-button-input
============================

Jquery plugin using bootstrap's radio button to implement a radio input like JQuery UI's.

JQuery UI and Bootstrap don't work well together. In particular, JQuery UI and Bootstrap both implement the "button" JQuery function, so anything in the "button" family of JQuery UI won't work. Normally this isn't too much of a problem, but one nice feature of JQuery UI is the radio button implementation which allows using radio buttons in a form, which bootstrap's normal radio button implementation does not.

This plugin seeks to fill that gap, when it is pointed at an existing radio input set (which should be set up similar to those used by the JQuery UI radio button set) it will build a bootstrap style radio button set which will keep the underlying radio input in sync.

The MIT License (MIT)

Copyright (c) 2013 Adam Griffis

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

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

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


text:
---
title: Cluster computing with a raspberry pi bramble
date: '2016-03-10T00:00:00.284Z'
tags: ['project', 'rpi', 'cluster computing']
thumbnail: './berries.jpg'
---

My goal here was to simply create a cluster of raspberry pi 3s (colloquially
referred to as a bramble).<!-- end -->Why? It seems like a pretty cheap way to build a
test bed for deploying to distributed systems (such as AWS). Overall this
setup cost around $240 but could be made much cheaper by using Raspberry Pi
Zeros and using USB OTG.

## Pretty straight forward equipment list:

![](https://lh3.googleusercontent.com/53Ch0rh3mhOL_vWvQ0sdLF-mxV551iJ1LNNBvDmSvOGfSm0mCIUujNVCAj9Vs-oWULKMXBf0LDGzAPQ6rtdbXGFiWT1RZ8yT3JzKkXK9xnI7B8zZeAC9alD2lDIYuC5tYnFfUDfapnJqXK77aoOR6_Xh47mPJxM-amqSPSBbJh6LwtmK11MiDx90Fsl_8e4w8z9KNpNRVc1U1q7_tKpcjpxliAUzO4LtEkroyh-L38sarccpYvrRMtik8jXFC3d0EJLFCNbQwdKB0-XIo0aPdLqv2yHXdVbbtiZCXQPc_4KH9wmsqcq2fmX4tmbfve80_tcrKYHRWL5BJmJlZJ5yA9mct_Eb2GOnlGuk57DqSi1Z1redJSyeo1J8gIL6qKi3jESeXkuaTzY_Og62Ybkvc8DELGbmscxoyaa4z708ghJX-DTHB_y30vKGHQ3yQc6ojvZjprQ0LoakwZ1JvWnafs3iZfdQm2bXKk68J-vHs24mVjIDRWDMLBU0K9pcYBTvsaob1fM8r54M4HGDahrAsZBdF0UXHtMUN3JLklKyzBNspWAmwZfK5d7a8dApzJTEdXToJkgz=s847-w634-h847-no)

- 4x Raspberry Pi 3
- 5 Port Switch
- 4x 16 GB Micro SD Cards
- 4x USB cables
- 4x Patch Cables
- And one neat stackable case to house them all

The result:

![](https://lh3.googleusercontent.com/GWOY8MkpBVF_rT5vPqFIlmIx402xq-rQebr-VWX21GFYOs_pi-Z2SaXvfngjd5vUtvRbEe2kAJ9k1tX-UPHRa2GzzJon4Oyyj-9B4nHryL6WcajcMTJP-CjqzZ_WDnXYIRicfOD6BMQGi5UArFSPD3JOL2Wm09Dip8UJdv4mKDKHkM794SbCNc52UAhg_En4y4mKebzDrrK7Ldyak_KFhkqsmMn3EwR5TGI6xC6KdXB_nJrOkjZEraq4k0FsdrQ2CJe9W_0dnL9_W3No5u9uFkxj4yQY1TcaBzsojyAFeiSKEyn-9YxiPpZSs8nbyTT3MMSwjMGsiIivaK7UU-jBGBdK2efEqZYmFd6Xj8HfUoIjy3W_SwBGjtKEGMMMe8BPgyufDSFe5stqNEfcQgwgNLPf8_6nupd9-o1hMBpHOaBrtr7dDX7NkJf89lJHL3VA_0tLDOYsHxfxiYKH6ON9dLHz9jDeip1T2wm_YGLspsWGSsNQpyh3EMENaxqyvAG1atNNCA1rGs6i5k2KfcaHBE654CbclvDySog19SbvrpIJNRi0UDhWKEqib_tcdvfqrutmKQvD1BJFE0rLvhFojE2-0JAZ-65zCt5b4cxF9FbRKZ7RlA=w1133-h847-no)

## OS

Initially I went with HypriotOS 1.0.1. Partially because of the awesome work
they've done into getting Docker (specifically 1.12) to run well on this
Raspbian derivitive. My understanding now is that Raspbian has good support
for Docker 1.12 out of the box (with a kernel update).

## First Steps To a Distributed Task Queue

My first goal was to create distributed compute task queue using Celery and
Redis. All running under Docker swarm mode such that I could easily spin up
containers of celery workers in the cloud. You can checkout my armv7
compatible docker image at https://hub.docker.com/r/deldreth/. The
hypriot/redis image works well enough out of the box (for testing purposes).
I will have another article at a later point detailing more information about
the rpi-python-celery image.

The good news is that everything works well enough considering the clock
speeds of the rpi3. Redis is a bit of memory hog (it tends to consume
everything it can--immediately). I've yet to try building an image for a
celery task broker using rabbitmq.

I'll have further updates on this project shortly. Right now I've been playing
around with running Apache Spark on a single master:three slave setup with the
cluster, but I want to continue working on the distributed task queue.

## Further Comments

If this is something that really interests you then I strongly suggest
checking out Docker Captain Alex Ellis' talk for
[Container Camp](https://www.youtube.com/watch?v=-qRUsuevKj4).


text:
---
name: Questions and help
about: If you think you need help with something related to Sapper
title: ''
labels: 'Question'
assignees: ''

---

This issue tracker is intended to collect bug reports and feature requests.

For help with installation, information on how features work, or questions about specific features of Sapper, please come and join us in the [Svelte Discord](https://svelte.dev/chat), or ask your question on [Stack Overflow](https://stackoverflow.com/questions/tagged/svelte). Any issues open for help requests will be closed to keep from clogging up the issue tracker.

repository: sveltejs/sapper

gha_language: TypeScript

repo_name: sveltejs/sapper


text:
# Reward Containers

Reward Containers is a package for Roblox game developers with built-in persistence (as makes sense) that can be swapped modularly to fit into any game's persistence schemes.
Reward Containers provide a framework for granting your players rewards. From simple things like badges to virtual currency and even loot boxes.
The point to Reward Containers is to provide a simple, modular system for rewarding players in games.

## Installation
### roblox-ts
Simply install to your [roblox-ts](https://roblox-ts.com/) project as follows:
```
npm i @rbxts/reward-containers
```

### Wally
[Wally](https://github.com/UpliftGames/wally/) users can install this package by adding the following line to their `Wally.toml` under `[dependencies]`:
```
RewardContainers =<EMAIL_ADDRESS>```

Then just run `wally install`.

### From model file
Model files are uploaded to every release as `.rbxmx` files. You can download the file from the [Releases page](https://github.com/Bytebit-Org/roblox-RewardContainers/releases) and load it into your project however you see fit.

### From model asset
New versions of the asset are uploaded with every release. The asset can be added to your Roblox Inventory and then inserted into your Place via Toolbox by getting it [here.](https://www.roblox.com/library/7881094056/Reward-Containers-Package)

## Documentation
Documentation can be found [here](https://github.com/Bytebit-Org/roblox-RewardContainers/tree/master/docs), is included in the TypeScript files directly, and was generated using [TypeDoc](https://typedoc.org/).

## Example
Let's see how to use this system to build a daily rewards system where users can come in, open their rewards, and then they lock for 24 hours. To start, we need to define our reward granters by their reward type in a map, like so:

```ts
import { VirtualCurrencyRewardGranter } from "@rbxts/reward-containers";

type CurrencyType = "coins" | "gems";

// Note we are assuming the currencyService here. In reality, this callback should be implemented to your game's specifications for virtual currency
const virtualCurrencyRewardGranter = VirtualCurrencyRewardGranter.create<CurrencyType>(
	(rewardedPlayer, currencyType, value) =>
		currencyService.awardCurrencyToPlayerAsync(rewardedPlayer, currencyType, value),
);

const rewardGrantersByType = new Map([["VirtualCurrency", virtualCurrencyRewardGranter]]);
```

Note that you can implement your own reward granters and use them here! `VirtualCurrencyRewardGranter` and `BadgeRewardGranter` are provided as part of the package and can serve as examples.

For this daily reward system, we'll be granting players one random reward every day they join from a list of rewards. You could list more, but for now let's just put an 80% chance at 100 coins and a 20% chance at 100 gems, like so:

```ts
import { WeightedRewardsSelector } from "@rbxts/reward-containers";

const rewardsSelector = WeightedRewardsSelector.create(
    1, // maximumNumberOfRewards
    [
        {
            reward: {
                type: "VirtualCurrency",
                currencyType: "coins",
                value: 100,
            },
            weight: 80,
        },
        {
            reward: {
                type: "VirtualCurrency",
                currencyType: "gems",
                value: 100,
            },
            weight: 20,
        },
    ],
    1, // value
)
```

The last thing we'll need before we're ready to create our reward container is a rewards opening coordinator. We'll use the standard one, like so:

```ts
import { StandardRewardsOpeningCoordinator } from "@rbxts/reward-containers";

const rewardsOpeningCoordinator = StandardRewardsOpeningCoordinator.create(rewardGrantersByType, rewardsSelector);
```

And now we're ready to set up our reward container that will have a 24-hour recurrence interval - aka our daily reward container! These need to be tied to a player, so we'll set this up in a player added handler.

```ts
import { Players } from "@rbxts/services";
import { RecurringTimeLockedRewardContainer } from "@rbxts/reward-containers";

Players.PlayerAdded.Connect((player) => {
    const rewardContainerForPlayer = RecurringTimeLockedRewardContainer.create(
        "DailyRewardContainer", // name
        24 * 60 * 60, // recurrenceIntervalInSeconds - set to 24 hours in seconds
        player, // rewardedPlayer
        rewardsOpeningCoordinator,
    );
});
```

Now just hook this up to your system for communicating to things to the client and providing a UI, and you're done!

repository: Bytebit-Org/roblox-RewardContainers

repo_name: Bytebit-Org/roblox-RewardContainers


text:
# Modal Model

## Introduction
The codes in this folder are to calculate the evolution of particle size distribution as the function of time with any initial particle size distribution.

## Modules

- **Modal_GDM.f90**: main program
- **global\_variables.f90**: define the global variables
- **read\_input.f90**: read the data from input files
- **derived\_parameters.f90**: contains several functions for coagulation coefficient, function for redistribution of particles between bins and subroutine to evaluate temperature dependent variables such as mean free path and viscosity
- **DVODE\_F90_M.f90**: module for ODE solver subroutine
- **rhs.f90**: ODE for the Smoluchowski equation (Modal)
- **calculations.f90**: calculate total number concentration and mean variables such as dpg, sigmag of the particle number distribution as the function of time

## Inputs

- **input.txt includes:
	- INITIAL PARTICLE PROPERTIES (Initial Vapor Pressure, Saturation Pressure and Vapor Generation Rate)
	- SPECIES PROPERTIES (Molecular Weight of the species, Density of the species and Surface Tension)
	- GAS PROPERTIES (Molecular Weight of gas, Density of gas at 298 K, Viscosity of gas at Tref = 298 K, Sutherland's Constant and Mean free path of gas molecules)
	- SYSTEM PROPERTIES (Pressure and Temperature)
	- SIMULATION TIME (Final time in seconds and Time step)
	- MODES (Number of modes)
	- AEROSOL PROCESSES (if ON set to 1) (Coagulation, Condensation and Nucleation)

## Outputs
- **results\_raw.dat**
	- **1st column**: Time in seconds
	- **Last column**: Vapor Concentration
	- **2k Column**: Number Concentration based in Mode k
	- **(2k+1) Column**: Total Volume of Mode k

- **results.dat**
	- **1st column**: Time in seconds
	- **2nd column**: Total Number Concentration (#/m3)
	- **3rd column**: Geometric Mean Diameter (m)
	- **4th column**: Geometric Standard Diameter

path: /AAQRL-ADM/Modal model/README.md


text:
---
layout: project_single
title:  "12 Classroom Behavior Books for Little Kids -"
slug: "12-classroom-behavior-books-for-little-kids"
parent: "what-is-behavior-analysis-examples"
---
Teaching students how to behave during the first few weeks of school will completely make or break your classroom for the entire school year. That's A LOT to take in and A LOT of pressure. I always find it incredibly beneficial to incorporate classroom behavior books into my lessons when teaching good and bad behaviors. They allow students to relate to the characters in the book and they can see examples of what it is expected of each of them when they are at school. Here are my favorite classro


text:
# Warning note

This library is still under development. We do **not** recommend using it yet since its features and/or interfaces might change in a nightly basis.

Also, it has not been tested properly yet. Test cases are still being designed as the library evolves, so its stability can't be guaranteed for now.

If you still want to use it, consider checking this library's behavior when debugging your project.

# About

Re-implementation of [Express.js](https://expressjs.com/) APIs, providing a simplified and further automatized usage, allowing developers to create web services much faster and with the same personalization levels.

# Setup

This library uses [@ricardofuzeto/ws-core](https://www.npmjs.com/package/@ricardofuzeto/ws-core) underneath. Because of this, it is mandatory to have a file `application.json` in your project's root, or the application will throw an error during startup.

For *ws-boot*, it is expected that such JSON file contains a `boot` property, where all *ws-boot* configuration will be. It should look like this:

```
// ...config data
  "boot": { /* ws-boot properties */ },
// ...config data
```

The following table shows all configuration fields that can be placed inside the `application.json` file and that will be recognized by *ws-boot*:

| field | type | default | description |
| ----- | :--: | :-----: | ----------- |
| port | number | 4000 | Port that Express's application will listen to |
| bodyType | string | "json" | Parser middleware type that will be applied to Express's request bodies. Accepted values: "json", "raw", "text" and "urlencoded". |
| cors | object | {} | CORS custom configuration to be applied to the Express application. For further information, see [CORS](https://www.npmjs.com/package/cors) |

# Booting the server

To boot your Express application via *ws-boot*, just add the following code:

```
const wsBoot = require('@ricardofuzeto/ws-boot');

wsBoot.init();
```

This will create an Express application, add all configurations previously defined and start it, 100% transparent to you. Also, you will see on console all configurations used to create the application.

# Routes

## Mapping new routes

To map a new route in your application, just import *ws-boot* and map directly from it:

```
wsBoot.get('/route1', (req, res) => {});
wsBoot.get('/route2', { options }, (req, res) => {});
```

This mapping augments what Express.js does, adding a log message for every mapped resource, allowing developers to know exactly what routes were mapped. Also, you can note the `options` object, which is an optional second argument. You can define custom options for a route, according to your needs. Check the section [Routes options](#routes-options) for further information.

## Supported HTTP methods

*ws-boot* does **not** support all HTTP methods. However, it does give enough support for a subset that satisfies the needs of almost all web service projects. Are the supported methods: DELETE, GET, PATCH, POST and PUT.

You can also use the ALL mapping from Express, but that is provided only for compatibility and flexibility purposes, and should be used only when absolutely no other method (even those in Express) is enough for what you need.

## Routes Options

As mentioned before, to add custom options to a route, you just have to pass an object as a second argument of the mapping function, like this:

```
wsBoot.get('/route1', { options }, (req, res) => {});
```

The `options` object currently support the following values:

| option | type | default | description |
| ----- | :--: | :-----: | ----------- |
| paginated | boolean | false | When set to `true`, the route's response will be paginated. *ws-boot* will only split returned data into pages, and handle the requested page via request's query field *page* |
| pageSize | number | 20 | Amount of results per page, when route's response is paginated |

# Contributors

Ricardo Fuzeto ([email](mailto:ricardofuzeto@gmail.com?subject=About%20ws-boot)): idea conception and initial development stages

repository: Fuzetaum/wsboot

repo_name: Fuzetaum/wsboot


text:
# Undecided

A safe way to evaluate a string boolean expression to make a decision

## Installation

Add this line to your application's Gemfile:

```ruby
gem 'undecided'
```

And then execute:

    $ bundle

Or install it yourself as:

    $ gem install undecided

## Usage

Initialize a decider instance

```ruby
decider = Undecided::Decider.new
```

Call decide method passing an string as a boolean expression and a hash with values (values must be boolean type or (1 or 0)

```ruby
expression = 'A&B'
values = { A:1, B:1 }
decider.decide(expression, values)
# Return true cuz A&B means that (A==true & B==true)
```

ATM the available operators are:
* & = AND
* | = OR
* ! = NOT
* () = Grouper

Imagine you have a todo list
```ruby
todo_a = {
			A:false,
			B:false,
			C:false
		 }
 # A,B and C are tasks
 # False means that task is incomplete
```
And you have a second todo list but, to start it, some conditions have to be fulfilled. i.e you have finished A and C or A and B. so

```ruby
# Start todo_b if

# common way

if todo_a[:A] == true & todo_a[:C] == true ||  todo_a[:A] == true and todo_a[:c]==true
  # start new todo list
end

# VS

decider = Undecided::decider.new

if decider.decide('A&B|A&C', todo_a)
  # start a new todo list
end

```

You can also evaluate more complex expression i.e
```ruby
rule = 'A&B&!C|(!C|!A)|D&F'
values = { A: 1, B: 1, C: 0, D: 0, F: 0 }

decider = Undecided::Decider.new
decider.decide(rule, values) #Return true
```
 'A&B&!C|(!C|!A)|D&F'

## Development

After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.

To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).

## Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/jotase/undecided.

## License

The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).

repository: JotaSe/undecided

gha_language: Ruby

repo_name: JotaSe/undecided


text:
# Stateful Startup

Some extensions, or parts of extensions, require the state to be loaded before starting itself up.  Without careful bootstrapping, this can lead to an object which has many unnecessary `if x is None` checks.

Instead, include a bootstrap that waits for the states to be registered.  The `StateWatch` class helps with this.

```python
from typing import Optional, Any
from petronia.aid.simp import (
    EventBus, EventId, ParticipantId,
    StateWatch, ListenerSet,
)
from some.extension import (
    STATE_ID_STATE1, State1,
    STATE_ID_STATE2, State2,
)

def bootstrap_component(bus: EventBus, listeners: ListenerSet):
    state1 = StateWatch(listeners, STATE_ID_STATE1, State1())
    state2 = StateWatch(listeners, STATE_ID_STATE2, State2())

    def check_startup(state: Any) -> None:
        if state1.is_set and state2.is_set:
            StatefulHandler(bus, listeners, state1, state2)

    state1.set_listener(check_startup)
    state2.set_listener(check_startup)

class StatefulHandler:
    def __init__(
            self, bus: EventBus, listeners: ListenerSet,
            state1: StateWatch[State1],
            state2: StateWatch[State2]
    ) -> None:
        state1.set_listener(self._on_state1)
        state2.set_listener(self._on_state2)
        ...

    def _on_state1(self, state: State1) -> None:
        ...

    def _on_state2(self, state: State2) -> None:
        ...
```

In this way, each state update is cached until all the states are ready.  Once the states are ready, the extension can begin.

repository: groboclown/petronia

gha_language: Python

gha_license_id: NOASSERTION

repo_name: groboclown/petronia


text:
# Kubernetes Operator for Armada and Helm

# Introduction

This README is mainly used a log / wiki of results and challenges encounted during the POC

## operator-sdk vs kubebuilder.

Things to clean up:
Did not had time to sort how to completly migrate from operator-sdh to kubebuilder.
Most of the scaffolding is done using the operator-sdk but once the default files are created,
the build process mainly relies on kubebuilder

## armada-operator code directory structure

###  cmd

Contains the main.go for the armada operator

###  pkg/apis/

Contains the golang definition of the CRDs. `make generate` will recreate the yaml definitions
of the CRDs that have to be provided to kubectl in order to deploy the new CRDs.
This current version of the operator uses "act" for shortname of ArmadaChart,
"acg" as shortname for ArmadaChartGroup and "amf" as shortname for ArmadaManifest.

The first version of the golang code has generated using tool such as "schema-generate" from
the schema definition provided with airship-armada project.

###  pkg/services

Contains the bulk of the interfaces used by the armada controller.

###  pkg/helm, pkg/helmv2 and pkg/helmv3

To get the process doing, some of the code for ArmadaChart handling is coming from the
operator-sdk helm-operator. That code is relying on tiller component which is gone for Helm3.
Hence the three directory helm (Interface and Common code), helmv2 (tiller) and helmv3.

The golang package structure is different between helmv2 and helmv3. The Armada Operator will
most likely ultimatly have support two branches. In order to delay that milestone, the golang
code has been instrumentated with "v2" and "v3" tags which allows to compile either the
helm v3 version of the operator or the helm v3 version.

###  pkg/armada directory

Mainly contain the code for ArmadaChartGroup, ArmadaManifest as will ArmadaBackupLocation handling

###  pkg/controller directory

Contains the controller and the "Reconcile" functions for ArmadaChart, ArmadaChartGroup and ArmadaManifest.
There are currently three controllers (act-controller, acg-controller and amf-controller).

# Code changes.

## Adjusting the ArmadaOperator CRDs

Upon change of the CRD golang definition, the yaml files have to be regenerated

Note 1: Don't understand yet how to build using operator-sdk operator with the same level of detailes than
controller-gen. Big hack that have to be included in Makefile.

Note 2: The generation tool seems to comply with some of OpenAPI specs. The "validation" schema added
to in the CRD yaml definition does not contain fields using underscore.
Most of those fields containing underscore where defined such a way in the original airship-armada.

```bash
make generate
```

## Compiling the armada-operator

To keep the directory tree ligthweight, the vendor directory is not checked in in the current repo.
TODO: Since the operator is only using one git branch, the developer has to comment out the helmv2
and add the helmv3 in Gopkg.toml if he wants to build the helmv3 version of the operator. This is still WIP.

```bash
dep ensure
```

To build the v2 version
```bash
make docker-build-v2
```

To build the v3 version
```bash
make docker-build-v3
```

## Run unit test and preintegration tests.

If you installed kubebuilder on your system, you will have access
to a standalone apiserver, etcd server and kubectl.

Because of a lack of time, the current makefile test statement,
will attempt to stop your kubelet and associated container in your local
kubernetes cluster, before starting apiserver, etcdserver.
TODO: We still need to figure out if it necessary

In order to run the unit tests and the e2e integration tests:
```bash
make unittest
```

# Deploying the operator.

Note the current deployment of the operator relies itself on helm.

To install the helm v2 version
```bash
make install-v2
```

To install the helm v3 version
```bash
make install-v3
```

# Testing the armada-controller

##  helm-charts/testchart directory

For testing purpose the current Docker file includes a dummy chart deliverd under armada-charts.
This removes the needs to access external chart repository which is also an aspect of helm changing from 2 to 3.

## examples/armada

In that directory, the ArmadaChart are enabled by default and the charts
are installed as soon as the ArmadaChart CRD are created.

### Deployment

Upon creation of the custom resource, the controller will
- Deploy the Armada Manifest described in the CRD
- Update status of the custom resources.
- Add events to the custom resources.

```bash
kubectl create -f examples/armada
kubectl describe amf/simple-armada
kubectl get amf
kubectl get acg
kubectl get act
```

### Test controller reconcilation logic (for depending resources)

Upon deletion of its depending resources, the controller will recreate it,

```bash
kubectl delete deployment.apps/blog-2-testchart
kubectl get all
kubectl describe act blog-2
```

### Test controller reconcilation logic (for CRD)

When deleting the CRD, the corresponding Armada Manifest should be uninstalled.

```bash
kubectl delete -f simple/armada
```

## examples/stepbystep

This directory contains invidual act,acg and amf files which allow the "step" by "step" testing of the deployment.

## examples/argo

In that directory, the ArmadaChart (act) are disabled by default and the charts not installed
automatically when the act CR are created.
This example assumes that the argo controller has been installed. When the "argo worflow"
CR is created, the "argo controller" is waked up and it orchestrates the enablement of the ArmadaChart
according to the worflow.

Note: You need to have argo installed in your cluster.

```bash
kubectl apply -f example/argo

armadachart.armada.airshipit.org/blog-1 created
armadachart.armada.airshipit.org/blog-2 created
workflow.argoproj.io/wf-blog-group created
```

The first ArmadaChart is installed:

```bash
kubectl get all

pod/armada-operator-cbbc7d7f7-zxj5n     1/1     Running             0          60s
pod/blog-1-testchart-5dd8c474f4-26574   0/1     ContainerCreating   0          6s
pod/wf-blog-group-1193326311            0/1     Completed           0          8s
pod/wf-blog-group-2026876860            0/1     ContainerCreating   0          1s
pod/wf-blog-group-2432013970            0/1     Completed           0          4s

NAME                       TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
service/armada-operator    ClusterIP   <IP_ADDRESS>    <none>        8383/TCP   57s
service/blog-1-testchart   ClusterIP   <IP_ADDRESS>   <none>        80/TCP     6s
service/kubernetes         ClusterIP   <IP_ADDRESS>      <none>        443/TCP    7m43s

NAME                               READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/armada-operator    1/1     1            1           60s
deployment.apps/blog-1-testchart   0/1     1            0           6s

NAME                                          DESIRED   CURRENT   READY   AGE
replicaset.apps/armada-operator-cbbc7d7f7     1         1         1       60s
replicaset.apps/blog-1-testchart-5dd8c474f4   1         1         0       6s
```

Later both charts have been installed

```bash
NAME                                    READY   STATUS      RESTARTS   AGE
pod/armada-operator-cbbc7d7f7-zxj5n     1/1     Running     0          44m
pod/blog-1-testchart-5dd8c474f4-26574   1/1     Running     0          43m
pod/blog-2-testchart-57f86dd9c5-xmhd7   1/1     Running     0          43m
pod/wf-blog-group-1193326311            0/1     Completed   0          43m
pod/wf-blog-group-2026876860            0/1     Completed   0          43m
pod/wf-blog-group-2234690393            0/1     Completed   0          43m
pod/wf-blog-group-2432013970            0/1     Completed   0          43m

NAME                       TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
service/armada-operator    ClusterIP   <IP_ADDRESS>      <none>        8383/TCP   44m
service/blog-1-testchart   ClusterIP   <IP_ADDRESS>     <none>        80/TCP     43m
service/blog-2-testchart   ClusterIP   <IP_ADDRESS>   <none>        80/TCP     43m
service/kubernetes         ClusterIP   <IP_ADDRESS>        <none>        443/TCP    51m

NAME                               READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/armada-operator    1/1     1            1           44m
deployment.apps/blog-1-testchart   1/1     1            1           43m
deployment.apps/blog-2-testchart   1/1     1            1           43m

NAME                                          DESIRED   CURRENT   READY   AGE
replicaset.apps/armada-operator-cbbc7d7f7     1         1         1       44m
replicaset.apps/blog-1-testchart-5dd8c474f4   1         1         1       43m
replicaset.apps/blog-2-testchart-57f86dd9c5   1         1         1       43m
```

argo is tracing the steps take to sequence the deployment of the charts:

```bash
argo get wf-blog-group

Name:                wf-blog-group
Namespace:           default
ServiceAccount:      armada-argo-sa
Status:              Succeeded
Created:             Fri Mar 22 10:27:28 -0500 (26 seconds ago)
Started:             Fri Mar 22 10:27:28 -0500 (26 seconds ago)
Finished:            Fri Mar 22 10:27:42 -0500 (12 seconds ago)
Duration:            14 seconds

STEP                  PODNAME                   DURATION  MESSAGE
 ✔ wf-blog-group
 ├---✔ enable-blog-1  wf-blog-group-1193326311  2s
 ├---✔ blog-1-ready   wf-blog-group-2432013970  3s
 ├---✔ enable-blog-2  wf-blog-group-2026876860  3s
 └---✔ blog-2-ready   wf-blog-group-2234690393  3s
 ```

We can check the state of the ArmadaChart

```bash
kubectl get act

NAME     STATE      TARGET STATE   SATISFIED
blog-1   deployed   deployed       true
blog-2   deployed   deployed       true
```

Run the cleanup
```bash

kubectl delete -f examples/argo
```

## examples/sequenced

In that directory, the ArmadaChart (act) are disabled by default and the charts not installed
automatically when the act CR are created.
When the "ArmadaChartGroup" CR is created, the "chartgroup controller" receives an event and it
orchestrate the order of deployment/enablement of the ArmadaChart. The ArmadaChartGroup also
becomes owner of the ArmadaChart.

This is basically the same sequencing that above except that it is implemented using an
ArmadaChartGroup and an ArmadaManifest

## examples/backup

This directory contains the CR definitions involved during an ArmadaBackup procedure.

- WIP

## examples/restore

This directory contains the CR definitions involved during an ArmadaRestore procedure.

- WIP

# Appendix

[POCs](./pocs/README.md) contains additional notes regarding successful and failed attempts.

repository: keleustes/armada-operator

gha_language: Go

repo_name: keleustes/armada-operator