[![All Contributors](https://img.shields.io/badge/all_contributors-26-orange.svg?style=flat-square)](#contributors-)
[![Issues](https://img.shields.io/github/issues-raw/thoughtworks/metrik.svg?style=flat)](https://github.com/thoughtworks/metrik/issues)
[![Licnece](https://img.shields.io/github/license/thoughtworks/metrik.svg?style=flat)](https://github.com/thoughtworks/metrik/blob/main/LICENSE.txt)

[![Backend test](https://github.com/thoughtworks/metrik/actions/workflows/backend_test.yaml/badge.svg)](https://github.com/thoughtworks/metrik/actions/workflows/backend_test.yaml)
[![Frontend test](https://github.com/thoughtworks/metrik/actions/workflows/frontend_test.yaml/badge.svg)](https://github.com/thoughtworks/metrik/actions/workflows/frontend_test.yaml)
[![codecov](https://codecov.io/gh/thoughtworks/metrik/branch/main/graph/badge.svg?token=KON1ADTCCD)](https://codecov.io/gh/thoughtworks/metrik)

[![Release](https://img.shields.io/github/v/release/thoughtworks/metrik.svg?include_prereleases&style=flat)](https://github.com/thoughtworks/metrik/releases)

      Maintained by SEA team, ThoughtWorks Inc.

*Read this in other languages:* [English](README.md), [简体中文](README-CH.md)

  Table of Contents

About the Project

Usage

How to Compute

Contributing

Getting Started

More

License

## About the Project

For development teams who wants to measure their software delivery and operational (SDO) performance, this is a tool
that helps them collect data from CD pipelines and visualize the key metrics in a friendly format.

**The key differentiators:**

* One page configuration, quick and easy.
* The ability to work across different CD platforms.
* User can select the environment in which the analysis runs via a environment filter (Yes, production env is not the
  only one that matters)

[Don't know what are those four key metrics?](https://www.thoughtworks.com/radar/techniques/four-key-metrics)

### Integration roadmap

List of CD tools the product supports now/plan to support

- [x] Jenkins
- [x] Bamboo
- [x] GitHub Actions
- [x] Buddy
- [ ] CircleCI

  ...and more on the way

## Usage

Follow the two steps below to run the tool, and measure the four key metrics of your projects.

### Install and run

The product is released to a public repository hosted on Docker Hub `docker.io/wszzwpshh1/metrik`. Please follow the
steps:

1. Ensure [Docker](https://www.docker.com) has already installed on your OS.
2. Find available [release versions](https://github.com/thoughtworks/metrik/releases) in the release page.
   Or, you can find all history versions from our [image repository](https://hub.docker.com/r/wszzwpshh1/metrik)
3. Run the container locally via the following command:

``` bash
docker run -d -p 80:80 --name metrik wszzwpshh1/metrik:latest
```

*⚠ We use port 80 to access the app. You may switch to any other port in case port 80 is occupied by other apps running
on your machine.*
*⚠ The `latest` tag matches the most recent version of this repository. Thus using wszzwpshh1/metrik:latest or
wszzwpshh1/metrik will ensure you are running the most up to date version of this image.*
If you want to stick to a specific version tag, remember there no "v" in version name. e.g. wszzwpshh1/metrik:latest:
1.6.5

### Configure your projects

After the container is running on your machine. Go to your favourite browser and open the app. If running in local that
would be `http://localhost:80/`.

1. Start the configuration:

2. And the charts for each key metric will be available at the main page:

3. Also the full screen view if you want to put it on big screens:

### Advanced usage

If you would like to keep the 4-key-metrics data to avoid losing any data when remove container, you
can mount the database folder `/data/db` out. And logs are also available if you mount the log folder `/app/logs`. As
shown in the example below:

``` bash
docker run -d -p 80:80 --name metrik -v "/path/to/local/directory:/data/db" -v "/path/to/another/directory:/app/logs" wszzwpshh1/metrik:${release_version}
```

## How to Compute, FAQs

[See our Wiki page](https://github.com/thoughtworks/metrik/wiki)

## Contributing

Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any
contributions you make are **greatly appreciated**.

Please check our contributing guideline form [HERE](CONTRIBUTING.md)

## Getting Started

The codebase comprises of three major components `frontend`, `backend`, `ci`.

* Frontend app is a web application built with:
    * TypeScript
    * ReactJS
    * ReCharts

  Go to [frontend folder](https://github.com/thoughtworks/metrik/tree/main/frontend) to find more details.

* Backend app is built with:
    * Kotlin
    * Spring Boot Web
    * MongoDB

  Go to [backend folder](https://github.com/thoughtworks/metrik/tree/main/backend) to find more details.

* Build/Package scripts lives in [ci folder](https://github.com/thoughtworks/metrik/tree/main/ci)

## More

You might also like:

* [Buildvis](https://github.com/cburgmer/buildviz), transparency for your build pipeline's results and runtime
* [HeartBeat](https://github.com/thoughtworks/HeartBeat), calculates delivery metrics from CI/CD build data, revision
  control and project planning tools.
* [GoCD Analytics Plugin](https://extensions-docs.gocd.org/analytics/current/), provides insights into your GoCD
  instance.

## License

Distributed under the MIT License. See [LICENSE](https://github.com/thoughtworks/metrik/blob/main/LICENSE.txt) for more
information

## Contributors ✨

Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):

Zhe ZHAO
💻

Hao Yang
💻

Jason Zhang
🚇

橘子小睿
💻

HUANG Binfang
💻

HeZhuConnie
💻

Mengqiu PENG
💻

Kiky
💻

Rong
💻

Piaopiao-TW
💻

zydxt
💻

ifeelcold1824
💻

快乐心情
💻

Taiyu Guo
💻

sasasakuna
💻

Chen
💻

ivy-pugai
💻

ZengXiaoXing
💻

HeyWen
💻

yong-wang1
💻

Paula Ferreira
🚇

twpei
💻

Henning S.
💻

Prateek
💻

Karuppiah Natarajan
💻

Fabio Formosa
📖

Zhongwen Lian
💻

Devonzhang
💻

Ashish Soni
💻

Marco Hutzsch
💻

Ikko Ashimine
📖

HE00L
💻

ATPEEE
💻

Sun Lixing
💻

RoujingLiu
💻

Ingridwyh090
💻

xloypaypa
💻

razu
💻

Wildan S. Nahar
💻

This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification.
Contributions of any kind welcome!


[![Tests](https://github.com/tangem/tangem-sdk-android/actions/workflows/tests.yml/badge.svg?branch=master)](https://github.com/tangem/tangem-sdk-android/actions/workflows/tests.yml)
[![Version](https://jitpack.io/v/Tangem/tangem-sdk-android.svg)](https://jitpack.io/#tangem/tangem-sdk-android)
[![License: MIT](https://img.shields.io/github/license/tangem/tangem-sdk-android)](LICENSE)
![Platform](https://img.shields.io/badge/platform-Android%20%7C%20JVM-blue)
[![Twitter](https://img.shields.io/twitter/follow/tangem?style=flat)](http://twitter.com/tangem)

# Welcome to Tangem

The Tangem card is a self-custodial hardware wallet that works via NFC. The main functions of Tangem cards are to securely create and store a private key and sign data.

Tangem SDK is needed to facilitate support for Tangem cards in third-party applications.

Supported platforms: [iOS](https://github.com/tangem/tangem-sdk-ios) | **Android** | **JVM** | [Flutter](https://github.com/tangem/tangem-sdk-flutter) | [React Native ](https://github.com/tangem/tangem-sdk-react-native) | [Cordova](https://github.com/tangem/tangem-sdk-cordova) | [Capacitor](https://github.com/tangem/tangem-sdk-cordova)

# Documentation

For exhaustive documentation, see [Tangem Developers Portal](https://developers.tangem.com).

To kick off the development process you can start with [Getting started for Android](https://developers.tangem.com/getting-started/android) page and [Getting started for JVM](https://developers.tangem.com/getting-started/jvm) page.

# License

Tangem SDK is available under the MIT license. See the [LICENSE](LICENSE) file for more info.


[![official JetBrains project](https://jb.gg/badges/official.svg)][jb:github]
[![Gradle Plugin Portal](https://img.shields.io/gradle-plugin-portal/v/org.jetbrains.intellij?color=green&label=Gradle%20Plugin%20Portal&logo=gradle)][gradle-plugin-page]
[![Build Status](https://github.com/JetBrains/gradle-intellij-plugin/workflows/Build/badge.svg)][gh:build]
[![TeamCity Build Status](https://teamcity.jetbrains.com/app/rest/builds/buildType:(id:OpenSourceProjects_GradleIntellijPlugin_UnitTests),branch:%3Cdefault%3E/statusIcon)][tc:build]
[![X Follow](https://img.shields.io/badge/follow-%40JBPlatform-1DA1F2?logo=x)][jb:x]
[![Slack](https://img.shields.io/badge/Slack-%23gradle--intellij--plugin-blue?style=flat-square&logo=Slack)][jb:slack]

![Gradle IntelliJ Plugin](.github/readme/gradle-intellij-plugin-dark.svg#gh-dark-mode-only)
![Gradle IntelliJ Plugin](.github/readme/gradle-intellij-plugin-light.svg#gh-light-mode-only)

# Gradle IntelliJ Plugin
The Gradle IntelliJ Plugin is a plugin for the Gradle build system to help configuring your environment for building, testing, verifying, and publishing plugins for IntelliJ-based IDEs.

## Documentation
The documentation of the Gradle IntelliJ Plugin has moved to the IntelliJ Platform Plugin SDK Documentation:
https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html

### Installation
To install the Gradle IntelliJ Plugin in your project, follow [Usage](https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html#usage) section of the plugin documentation.
There's also a [Snapshot Release](https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html#snapshot-release) available built nightly form the main branch containing the always-latest version of the plugin.

## Changelog
All releases are available in the [Releases](https://github.com/JetBrains/gradle-intellij-plugin/releases) section.
The latest available version is:

[![Gradle Plugin Portal](https://img.shields.io/gradle-plugin-portal/v/org.jetbrains.intellij?color=green&label=Gradle%20Plugin%20Portal&logo=gradle)](https://plugins.gradle.org/plugin/org.jetbrains.intellij)

## Contributing
Please see [CONTRIBUTING](./CONTRIBUTING.md) on how to submit feedback and contribute to this project.

## License
Licensed under the Apache License, Version 2.0 (the "License"), see [LICENCE](./LICENSE).

[gh:build]: https://github.com/JetBrains/gradle-intellij-plugin/actions/workflows/build.yml
[jb:github]: https://github.com/JetBrains/.github/blob/main/profile/README.md
[jb:slack]: https://plugins.jetbrains.com/slack
[jb:x]: https://twitter.com/JBPlatform
[tc:build]: https://teamcity.jetbrains.com/project/OpenSourceProjects_GradleIntellijPlugin?mode=builds
[gradle-plugin-page]: https://plugins.gradle.org/plugin/org.jetbrains.intellij


# Kotlin DataFrame: typesafe in-memory structured data processing for JVM
[![JetBrains incubator project](https://jb.gg/badges/incubator.svg)](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub)
[![Kotlin component alpha stability](https://img.shields.io/badge/project-alpha-kotlin.svg?colorA=555555&colorB=DB3683&label=&logo=kotlin&logoColor=ffffff&logoWidth=10)](https://kotlinlang.org/docs/components-stability.html)
[![Kotlin](https://img.shields.io/badge/kotlin-1.9.22-blue.svg?logo=kotlin)](http://kotlinlang.org)
[![Dynamic XML Badge](https://img.shields.io/badge/dynamic/xml?url=https%3A%2F%2Frepo1.maven.org%2Fmaven2%2Forg%2Fjetbrains%2Fkotlinx%2Fdataframe%2Fmaven-metadata.xml&query=%2F%2Fversion%5Bnot%28contains%28text%28%29%2C%22dev%22%29%29%5D%5Blast%28%29%5D&label=Release%20version)](https://search.maven.org/artifact/org.jetbrains.kotlinx/dataframe)
[![Dynamic XML Badge](https://img.shields.io/badge/dynamic/xml?url=https%3A%2F%2Frepo1.maven.org%2Fmaven2%2Forg%2Fjetbrains%2Fkotlinx%2Fdataframe%2Fmaven-metadata.xml&query=%2F%2Fversion%5Bcontains%28text%28%29%2C%22dev%22%29%5D%5Blast%28%29%5D&label=Dev%20version&color=yellow
)](https://search.maven.org/artifact/org.jetbrains.kotlinx/dataframe)
[![GitHub License](https://img.shields.io/badge/license-Apache%20License%202.0-blue.svg?style=flat)](http://www.apache.org/licenses/LICENSE-2.0)
[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/Kotlin/dataframe/HEAD)

Kotlin DataFrame aims to reconcile Kotlin's static typing with the dynamic nature of data by utilizing both the full power of the Kotlin language and the opportunities provided by intermittent code execution in Jupyter notebooks and REPL.

* **Hierarchical** — represents hierarchical data structures, such as JSON or a tree of JVM objects.
* **Functional** — data processing pipeline is organized in a chain of `DataFrame` transformation operations. Every operation returns a new instance of `DataFrame` reusing underlying storage wherever it's possible.
* **Readable** — data transformation operations are defined in DSL close to natural language.
* **Practical** — provides simple solutions for common problems and the ability to perform complex tasks.
* **Minimalistic** — simple, yet powerful data model of three column kinds.
* **Interoperable** — convertable with Kotlin data classes and collections.
* **Generic** — can store objects of any type, not only numbers or strings.
* **Typesafe** — on-the-fly generation of extension properties for type safe data access with Kotlin-style care for null safety.
* **Polymorphic** — type compatibility derives from column schema compatibility. You can define a function that requires a special subset of columns in a dataframe but doesn't care about other columns.

Integrates with [Kotlin kernel for Jupyter](https://github.com/Kotlin/kotlin-jupyter). Inspired by [krangl](https://github.com/holgerbrandl/krangl), Kotlin Collections and [pandas](https://pandas.pydata.org/)

## Documentation

Explore [**documentation**](https://kotlin.github.io/dataframe/overview.html) for details.

You could find the following articles there:

* [Get started with Kotlin DataFrame](https://kotlin.github.io/dataframe/gettingstarted.html)
* [Working with Data Schemas](https://kotlin.github.io/dataframe/schemas.html)
* [Full list of all supported operations](https://kotlin.github.io/dataframe/operations.html)
    * [Reading from SQL databases](https://kotlin.github.io/dataframe/readsqldatabases.html)
    * [Reading/writing from/to different file formats like JSON, CSV, Apache Arrow](https://kotlin.github.io/dataframe/read.html)
    * [Joining dataframes](https://kotlin.github.io/dataframe/join.html)
    * [GroupBy operation](https://kotlin.github.io/dataframe/groupby.html)
* [Rendering to HTML](https://kotlin.github.io/dataframe/tohtml.html#jupyter-notebooks)

## Setup

```kotlin
implementation("org.jetbrains.kotlinx:dataframe:0.13.1")
```

Optional Gradle plugin for enhanced type safety and schema generation
https://kotlin.github.io/dataframe/schemasgradle.html
```kotlin
id("org.jetbrains.kotlinx.dataframe") version "0.13.1"
```

Check out the [custom setup page](https://kotlin.github.io/dataframe/gettingstartedgradleadvanced.html) if you don't need some of the formats as dependencies,
for Groovy, and for configurations specific to Android projects.

## Getting started

```kotlin
import org.jetbrains.kotlinx.dataframe.*
import org.jetbrains.kotlinx.dataframe.api.*
import org.jetbrains.kotlinx.dataframe.io.*
```

```kotlin
val df = DataFrame.read("https://raw.githubusercontent.com/Kotlin/dataframe/master/data/jetbrains_repositories.csv")
df["full_name"][0] // Indexing https://kotlin.github.io/dataframe/access.html

df.filter { "stargazers_count"<Int>() > 50 }.print()
```

## Getting started with data schema

Requires Gradle plugin to work
```kotlin
id("org.jetbrains.kotlinx.dataframe") version "0.13.1"
```

Plugin generates extension properties API for provided sample of data. Column names and their types become discoverable in completion.

```kotlin
// Make sure to place the file annotation above the package directive
@file:ImportDataSchema(
    "Repository",
    "https://raw.githubusercontent.com/Kotlin/dataframe/master/data/jetbrains_repositories.csv",
)

package example

import org.jetbrains.kotlinx.dataframe.annotations.ImportDataSchema
import org.jetbrains.kotlinx.dataframe.api.*

fun main() {
    // execute `assemble` to generate extension properties API
    val df = Repository.readCSV()
    df.fullName[0]

    df.filter { stargazersCount > 50 }
}
```

## Getting started in Jupyter Notebook / Kotlin Notebook

Install the [Kotlin kernel](https://github.com/Kotlin/kotlin-jupyter) for [Jupyter](https://jupyter.org/)

Import the stable `dataframe` version into a notebook:
```
%use dataframe
```
or a specific version:
```
%use dataframe(<version>)
```

```kotlin
val df = DataFrame.read("https://raw.githubusercontent.com/Kotlin/dataframe/master/data/jetbrains_repositories.csv")
df // the last expression in the cell is displayed
```

When a cell with a variable declaration is executed, in the next cell `DataFrame` provides extension properties based on its data
```kotlin
df.filter { stargazers_count > 50 }
```

## Data model
* `DataFrame` is a list of columns with equal sizes and distinct names.
* `DataColumn` is a named list of values. Can be one of three kinds:
  * `ValueColumn` — contains data
  * `ColumnGroup` — contains columns
  * `FrameColumn` — contains dataframes

## Syntax example

Let us show you how data cleaning and aggregation pipelines could look like with DataFrame.

**Create:**
```kotlin
// create columns
val fromTo by columnOf("LoNDon_paris", "MAdrid_miLAN", "londON_StockhOlm", "Budapest_PaRis", "Brussels_londOn")
val flightNumber by columnOf(10045.0, Double.NaN, 10065.0, Double.NaN, 10085.0)
val recentDelays by columnOf("23,47", null, "24, 43, 87", "13", "67, 32")
val airline by columnOf("KLM(!)", "{Air France} (12)", "(British Airways. )", "12. Air France", "'Swiss Air'")

// create dataframe
val df = dataFrameOf(fromTo, flightNumber, recentDelays, airline)

// print dataframe
df.print()
```

**Clean:**
```kotlin
// typed accessors for columns
// that will appear during
// dataframe transformation
val origin by column<String>()
val destination by column<String>()

val clean = df
    // fill missing flight numbers
    .fillNA { flightNumber }.with { prev()!!.flightNumber + 10 }

    // convert flight numbers to int
    .convert { flightNumber }.toInt()

    // clean 'airline' column
    .update { airline }.with { "([a-zA-Z\\s]+)".toRegex().find(it)?.value ?: "" }

    // split 'fromTo' column into 'origin' and 'destination'
    .split { fromTo }.by("_").into(origin, destination)

    // clean 'origin' and 'destination' columns
    .update { origin and destination }.with { it.lowercase().replaceFirstChar(Char::uppercase) }

    // split lists of delays in 'recentDelays' into separate columns
    // 'delay1', 'delay2'... and nest them inside original column `recentDelays`
    .split { recentDelays }.inward { "delay$it" }

    // convert string values in `delay1`, `delay2` into ints
    .parse { recentDelays }
```

**Aggregate:**
```kotlin
clean
    // group by the flight origin renamed into "from"
    .groupBy { origin named "from" }.aggregate {
        // we are in the context of a single data group

        // total number of flights from origin
        count() into "count"

        // list of flight numbers
        flightNumber into "flight numbers"

        // counts of flights per airline
        airline.valueCounts() into "airlines"

        // max delay across all delays in `delay1` and `delay2`
        recentDelays.maxOrNull { delay1 and delay2 } into "major delay"

        // separate lists of recent delays for `delay1`, `delay2` and `delay3`
        recentDelays.implode(dropNA = true) into "recent delays"

        // total delay per destination
        pivot { destination }.sum { recentDelays.colsOf<Int?>() } into "total delays to"
    }
```

Check it out on [**Datalore**](https://datalore.jetbrains.com/view/notebook/vq5j45KWkYiSQnACA2Ymij) to get a better visual impression of what happens and what the hierarchical dataframe structure looks like.

Explore [**more examples here**](examples).

## Kotlin, Kotlin Jupyter, OpenAPI, Arrow and JDK versions

This table shows the mapping between main library component versions and minimum supported Java versions.

| Kotlin DataFrame Version | Minimum Java Version | Kotlin Version | Kotlin Jupyter Version | OpenAPI version | Apache Arrow version |
|--------------------------|----------------------|----------------|------------------------|-----------------|----------------------|
| 0.10.0                   | 8                    | 1.8.20         | 0.11.0-358             | 3.0.0           | 11.0.0               |
| 0.10.1                   | 8                    | 1.8.20         | 0.11.0-358             | 3.0.0           | 11.0.0               |
| 0.11.0                   | 8                    | 1.8.20         | 0.11.0-358             | 3.0.0           | 11.0.0               |
| 0.11.1                   | 8                    | 1.8.20         | 0.11.0-358             | 3.0.0           | 11.0.0               |
| 0.12.0                   | 8                    | 1.9.0          | 0.11.0-358             | 3.0.0           | 11.0.0               |
| 0.12.1                   | 8                    | 1.9.0          | 0.11.0-358             | 3.0.0           | 11.0.0               |
| 0.13.1                   | 8                    | 1.9.22         | 0.12.0-139             | 3.0.0           | 15.0.0               |

## Code of Conduct

This project and the corresponding community are governed by the [JetBrains Open Source and Community Code of Conduct](https://confluence.jetbrains.com/display/ALL/JetBrains+Open+Source+and+Community+Code+of+Conduct). Please make sure you read it.

## License

Kotlin DataFrame is licensed under the [Apache 2.0 License](LICENSE).


# EVM-based Chains

The source data is in _data/chains. Each chain has its own file with the filename being the [CAIP-2](https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-2.md) representation as name and `.json` as extension.

## Example

```json
{
  "name": "Ethereum Mainnet",
  "chain": "ETH",
  "rpc": [
    "https://mainnet.infura.io/v3/${INFURA_API_KEY}",
    "https://api.mycryptoapi.com/eth"
  ],
  "faucets": [],
  "nativeCurrency": {
    "name": "Ether",
    "symbol": "ETH",
    "decimals": 18
  },
  "features": [{ "name": "EIP155" }, { "name": "EIP1559" }],
  "infoURL": "https://ethereum.org",
  "shortName": "eth",
  "chainId": 1,
  "networkId": 1,
  "icon": "ethereum",
  "explorers": [{
    "name": "etherscan",
    "url": "https://etherscan.io",
    "icon": "etherscan",
    "standard": "EIP3091"
  }]
}
```

when an icon is used in either the network or an explorer there must be a json in _data/icons with the name used (e.g. in the above example there must be a `ethereum.json` and a `etherscan.json` in there) - the icon jsons look like this:

```json

[
    {
      "url": "ipfs://QmdwQDr6vmBtXmK2TmknkEuZNoaDqTasFdZdu3DRw8b2wt",
      "width": 1000,
      "height": 1628,
      "format": "png"
    }
]

```

where:
 * the URL must be an IPFS url that is publicly resolvable
 * width and height are positive integers
 * format is either "png", "jpg" or "svg"

If the chain is an L2 or a shard of another chain you can link it to the parent chain like this:

```json
{
  ...
  "parent": {
   "type" : "L2",
   "chain": "eip155-1",
   "bridges": [ {"url":"https://bridge.arbitrum.io"} ]
  }
}
```

where you need to specify type 2 and the reference to an existing parent. The field about bridges is optional.

You can add a `status` field e.g. to deprecate (via status `deprecated`) a chain (a chain should never be deleted as this would open the door to replay attacks)
Other options for `status` are `active` (default) or `incubating`

## Aggregation

There are also aggregated json files with all chains automatically assembled:
 * https://chainid.network/chains.json
 * https://chainid.network/chains_mini.json (miniaturized - fewer fields for smaller filesize)

## Constraints

 * the shortName and name MUST be unique - see e.g. EIP-3770 on why
 * if referencing a parent chain - the chain MUST exist in the repo
 * if using a IPFS CID for the icon - the CID MUST be retrievable via `ipfs get` - not only through some gateway (means please do not use pinata for now)
 * for more constraints you can look into the CI

## Collision management

 We cannot allow more than one chain with the same chainID - this would open the door to replay attacks.
 The first pull request gets the chainID assigned. When creating a chain we can expect that you read EIP155 which states this repo.
 All pull requests trying to replace a chainID because they think their chain is better than the other will be closed.
 The only way to get a chain reassigned is when the old chain gets deprecated. This can e.g. be used for testnets that are short-lived. But then you will get the redFlag "reusedChaiID" that should be displayed in clients to warn them about the dangers here.

## Getting your PR merged
### before PR is submitted

Before submitting a PR, please verify that checks pass with:

```bash
$ ./gradlew run

BUILD SUCCESSFUL in 7s
9 actionable tasks: 9 executed
```

Also please run the prettier to format your json according to the style [defined here ](https://github.com/ethereum-lists/chains/blob/master/.prettierrc.json)
e.g. run

```
npx prettier --write _data/*/*.json
```

### Once PR is submitted

 * Make sure CI is green. There will likely be no review when the CI is red.
 * When making changes that fix the CI problems - please re-request a review - otherwise it is too much work to track such changes with so many PRs daily

## Usages
### Tools
 * [MESC](https://paradigmxyz.github.io/mesc)

### Explorers
 * [Otterscan](https://otterscan.io)

### Wallets
 * [WallETH](https://walleth.org)
 * [TREZOR](https://trezor.io)
 * [Minerva Wallet](https://minerva.digital)

### EIPs
 * EIP-155
 * EIP-3014
 * EIP-3770
 * EIP-4527

### Listing sites
 * [chainid.network](https://chainid.network) / [chainlist.wtf](https://chainlist.wtf)
 * [chainlist.org](https://chainlist.org)
 * [Chainlink docs](https://docs.chain.link/)
 * [dRPC Chainlist - Load-balanced public nodes](https://drpc.org/chainlist)
 * [eth-chains](https://github.com/taylorjdawson/eth-chains)
 * [EVM-BOX](https://github.com/izayl/evm-box)
 * [evmchain.info](https://evmchain.info)
 * [evmchainlist.org](https://evmchainlist.org)
 * [networks.vercel.app](https://networks.vercel.app)
 * [Wagmi compatible chain configurations](https://spenhouet.com/chains)

### Other
 * [FaucETH](https://github.com/komputing/FaucETH)
 * [Sourcify playground](https://playground.sourcify.dev)
 * [Smart Contract UI](https://xtools-at.github.io/smartcontract-ui)

 * Your project - contact us to add it here!


# eco
eco is a powerful Spigot plugin framework that simplifies the process of plugin creation and supercharges
your plugins.
It's the engine behind [EcoEnchants](https://polymart.org/resource/490), [Reforges](https://polymart.org/resource/1330),
[EcoItems](https://polymart.org/resource/1247), [EcoSkills](https://polymart.org/resource/1351),
[EcoArmor](https://polymart.org/resource/687), [Talismans](https://polymart.org/resource/611),
and many more.

eco comes packed with all the tools you need in your plugins:

- Modern command API
- Native color parsing with full hex/RGB/MiniMessage support
- Yaml/JSON/TOML config system
- Persistent data storage API with Yaml/MySQL/MongoDB support
- Packet item display system
- Lightweight event loop based packet API
- Entity AI API with near-1:1 NMS mappings
- More events
- Extension API, essentially plugins for plugins
- Fluent dependency injection for NamespacedKey, Metadata values, etc.
- Ultra-fast ItemStack reimplementation bypassing ItemMeta
- Complete GUI API with pre-made components available from [ecomponent](https://github.com/Auxilor/ecomponent)
- Over 30 native integrations for other plugins
- First-class custom item support with lookup strings
- Math expression parsing via [Crunch](https://github.com/Redempt/Crunch)
- Particle lookups
- Complete Placeholder API
- Price system, supporting economy plugins, XP, Items, etc.
- NMS/Version-specific tooling
- Custom crafting recipe API with support for stacks and custom items
- Native plugin update checking
- Native bStats support
- Full Kotlin support and native extensions
- Tooling to make meta-frameworks, like [libreforge](https://github.com/Auxilor/libreforge)
- And much more

# For server owners
- Supports 1.17+

## Downloads

- Stable: [GitHub](https://github.com/Auxilor/eco/releases), [Polymart](https://polymart.org/resource/eco.773)
- Dev: [GitHub](https://github.com/Auxilor/eco/actions/workflows/java-ci.yml) (Open latest run and download)

# For developers

## Javadoc
The 6.53.0 Javadoc can be found [here](https://javadoc.jitpack.io/com/willfp/eco/6.53.0/javadoc/)

## Plugin Information

eco is a standalone plugin, so you will need to install it on any servers that have plugins which depend on it,
and specify it as a dependency in your plugin.yml:

```yaml
depend:
  - eco
```

## Dependency Information:

Gradle:

```kts
repositories {
        maven("https://repo.auxilor.io/repository/maven-public/")
}

```

```groovy
dependencies {
        compileOnly("com.willfp:eco:Tag")
}
```

Replace `Tag` with a release tag for eco, eg `6.53.0`.

Maven:

```xml
<repository>
        <id>auxilor</id>
        <url>https://repo.auxilor.io/repository/maven-public/</url>
</repository>
```

```xml
<dependency>
        <groupId>com.willfp</groupId>
        <artifactId>eco</artifactId>
        <version>Tag</version>
        <scope>provided</scope>
</dependency>
```

Replace `Tag` with a release tag for eco, eg `6.53.0`.

## Build locally:

Run the following commands in your terminal of choice.

If you're on windows, you will need to have git bash installed.
```
git clone https://github.com/Auxilor/eco
cd eco
./gradlew build
```

## License

eco is licensed under the MIT license. *Click here to read [the entire license](https://github.com/Auxilor/eco/blob/master/LICENSE.md).*

  Check out our partners!


### Specs
[![API](https://img.shields.io/badge/API-17%2B-yellow.svg?style=flat)](https://android-arsenal.com/api?level=17)
[![License](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

## Exponea Android SDK

This library allows you to interact from your application or game with the Bloomreach Engagement.

Bloomreach Engagement empowers B2C marketers to raise conversion rates, improve acquisition ROI, and maximize customer lifetime value.

It has been written 100% in Kotlin with ❤

>
> Bloomreach Engagement was formerly known as Exponea. For backward compatibility, the Exponea name continues to be used in the iOS SDK.

## 📦 Installation

### Download

Download via Gradle:

```groovy
dependencies {
  implementation 'com.exponea.sdk:sdk:3.14.0'
}
```

Download via Maven:

```groovy
<dependency>
    <groupId>com.exponea.sdk</groupId>
    <artifactId>sdk</artifactId>
    <version>3.14.0</version>
</dependency>
```

## 📱 Demo Application

Check out our [sample project](https://github.com/exponea/exponea-android-sdk/tree/master/app) to try it yourself! 😉

## 💻 Usage

### Getting Started

Follow the detailed [step by step guide here](https://documentation.bloomreach.com/engagement/docs/android-sdk-setup) to get started.

### Documentation

- [Initial SDK Setup](https://documentation.bloomreach.com/engagement/docs/android-sdk-setup)
  - [Configuration](https://documentation.bloomreach.com/engagement/docs/android-sdk-configuration)
  - [Authorization](https://documentation.bloomreach.com/engagement/docs/android-sdk-authorization)
  - [Data Flushing](https://documentation.bloomreach.com/engagement/docs/android-sdk-data-flushing)
- [Tracking](https://documentation.bloomreach.com/engagement/docs/android-sdk-tracking)
  - [Tracking Consent](https://documentation.bloomreach.com/engagement/docs/android-sdk-tracking-consent)
- [Android App Links](https://documentation.bloomreach.com/engagement/docs/android-sdk-app-links)
- [Push Notifications](https://documentation.bloomreach.com/engagement/docs/android-sdk-push-notifications)
  - [Firebase Cloud Messaging](https://documentation.bloomreach.com/engagement/docs/android-sdk-configure-firebase)
  - [Huawei Mobile Services](https://documentation.bloomreach.com/engagement/docs/android-sdk-configure-huawei)
- [Fetch Data](https://documentation.bloomreach.com/engagement/docs/android-sdk-fetch-data)
- [In-App Personalization](https://documentation.bloomreach.com/engagement/docs/android-sdk-in-app-personalization)
  - [In-App Messages](https://documentation.bloomreach.com/engagement/docs/android-sdk-in-app-messages)
  - [In-App Content Blocks](https://documentation.bloomreach.com/engagement/docs/android-sdk-in-app-content-blocks)
- [App Inbox](https://documentation.bloomreach.com/engagement/docs/android-sdk-app-inbox)
- [Segmentation](https://documentation.bloomreach.com/engagement/docs/android-sdk-segmentation)
- [Example App](https://documentation.bloomreach.com/engagement/docs/android-sdk-example-app)
- [Release Notes](https://documentation.bloomreach.com/engagement/docs/android-sdk-release-notes)
   - [SDK Version Update Guide](https://documentation.bloomreach.com/engagement/docs/android-sdk-version-update)

## 🔗 Useful links

* [Bloomreach Engagement App](https://app.exponea.com/login)

## 📝 Release Notes

Release notes can be found [here](https://documentation.bloomreach.com/engagement/docs/android-sdk-release-notes).

## ⚠ Version Disclaimer

This SDK supports **API 17+** and **Android 4.2+**. If you wish to interact with Bloomreach Engagement on lower API/Android versions please refer to the [old SDK located here](https://github.com/infinario/android-sdk).

## Support

Are you a Bloomreach customer and dealing with some issues on mobile SDK? You can reach the official Engagement Support [via these recommended ways](https://documentation.bloomreach.com/engagement/docs/engagement-support#contacting-the-support).
Note that Github repository issues and PRs will also be considered but with the lowest priority and without guaranteed output.


# AWS SDK for Kotlin
[![Apache 2 licensed][apache-badge]][apache-url] [![Maven][maven-badge]][maven-url]

[apache-badge]: https://img.shields.io/badge/license-APACHE2-blue.svg
[apache-url]: https://github.com/awslabs/aws-sdk-kotlin/blob/main/LICENSE

[maven-badge]: https://img.shields.io/maven-central/v/aws.sdk.kotlin/s3.svg?label=Maven
[maven-url]: https://search.maven.org/search?q=g:aws.sdk.kotlin

This repo contains the AWS SDK for Kotlin and its [public roadmap](https://github.com/awslabs/aws-sdk-kotlin/projects/2).

## Getting Started

* [SDK Homepage](https://aws.amazon.com/sdk-for-kotlin/)
* [Developer Guide](https://docs.aws.amazon.com/sdk-for-kotlin/latest/developer-guide/home.html)
* [API Reference](https://sdk.amazonaws.com/kotlin/api/latest/index.html)
* [Samples](https://github.com/awsdocs/aws-doc-sdk-examples/tree/main/kotlin)

See the [Getting Started Guide](docs/GettingStarted.md) to learn how to use the AWS SDK for Kotlin in your program.

## Feedback

The SDK uses **GitHub Issues** to track feature requests and issues with the SDK. In addition, we use **GitHub Projects**
to provide a high level overview of our roadmap and the features we are actively working on.

You can provide feedback or report a bug by submitting an [issue](https://github.com/awslabs/aws-sdk-kotlin/issues/new/choose).
This is the preferred mechanism to give feedback so that other users can engage in the conversation, +1 issues, etc.

## Contributing

If you are interested in contributing to the AWS SDK for Kotlin, please take a look at [CONTRIBUTING](CONTRIBUTING.md)

## Versioning

See our [VERSIONING](VERSIONING.md) policy for how the SDK is versioned.

## Development

### Generate SDK(s)

Generated sources are not checked into the repository, you first have to generate the clients before you can build them.
A [step-by-step guide](docs/generate-sdk.md) is available that demonstrates building the AWS DynamoDB service, or if
you have a good working knowledge of Gradle, see below:

```sh
./gradlew --no-daemon :codegen:sdk:bootstrap
```

NOTE: This task will respect the AWS services specified by project properties. See options below.
NOTE: To re-run codegen for the same set of services multiple times add the `--rerun-tasks` flag.

After generating the services you care about they are available to build:

e.g.
```sh
./gradlew :services:lambda:build
```

Where the task follows the pattern: `:services:SERVICE:build`

To see list of all projects run `./gradlew projects`

##### Generating a single service
See the [Build Properties](#build-properties) below to specify this in a config file.

```sh
./gradlew --no-daemon -Paws.services=+lambda  :codegen:sdk:bootstrap
```

##### Testing Locally
Testing generated services generally requires publishing artifacts (e.g. client-runtime) of `smithy-kotlin`, `aws-crt-kotlin`, and `aws-sdk-kotin` to maven local.

#### Generating API Documentation

API documentation is generated using [Dokka](http://kotlin.github.io/dokka) which is the official documentation tool maintained by JetBrains for documenting Kotlin code.

Unlike Java, Kotlin uses its own [KDoc](https://kotlinlang.org/docs/kotlin-doc.html) format.

To generate API reference documentation for the AWS Kotlin SDK:

```sh
./gradlew --no-daemon --no-parallel dokkaHtmlMultiModule
```

This will output HTML formatted documentation to `build/dokka/htmlMultiModule`

NOTE: You currently need an HTTP server to view the documentation in browser locally. You can either use the builtin server in Intellij or use your favorite local server (e.g. `python3 -m http.server`). See [Kotlin/dokka#1795](https://github.com/Kotlin/dokka/issues/1795)

### Build Properties

You can define a `local.properties` config file at the root of the project to modify build behavior.

|Property|Description|
|---|---|
|`compositeProjects`|Specify paths to repos the SDK depends upon such as `smithy-kotlin`|
|`aws.services`|Specify inclusions (+ prefix) and exclusions (- prefix) of service names to generate|
|`aws.protocols`|Specify inclusions (+ prefix) and exclusions (- prefix) of AWS protocols to generate|

#### Composite Projects

Dependencies of the SDK can be added as composite build such that multiple repos may appear as one
holistic source project in the IDE.

```ini
# comma separated list of paths to `includeBuild()`
# This is useful for local development of smithy-kotlin in particular
compositeProjects=../smithy-kotlin
```

#### Generating Specific Services Based on Name or Protocol

A comma separated list of services to include or exclude for generation from codegen/sdk/aws-models may
be specified with the `aws.services` property. A list of protocols of services to generate may be specified
with the `aws.protocols` property.

Included services require a '+' character prefix and excluded services require a '-' character.
If any items are specified for inclusion, only specified included members will be generated.  If no items
are specified for inclusion, all members not excluded will be generated.
When unspecified all services found in the directory specified by the `modelsDir` property are generated.
Service names match the filenames in the models directory `service.VERSION.json`.

Some example entries for `local.properties`:
```ini
# Generate only AWS Lambda:
aws.services=+lambda
```

```ini
# Generate all services but AWS location and AWS DynamoDB:
aws.services=-location,-dynamodb
```

```ini
# Generate all services except those using the restJson1 protocol:
aws.protocols=-restJson1
```

### Debugging

See [Debugging](docs/debugging.md)

## Security

Please refer to our [security policy](https://github.com/awslabs/aws-sdk-kotlin/security/policy).

## Supported targets

The SDK supports the following targets:

* [JVM](docs/targets.md#jvm)
* [Android](docs/targets.md#android)


AAIdrive
========

[![Build Status](https://img.shields.io/github/actions/workflow/status/BimmerGestalt/AAIdrive/android-build.yml?branch=main)](https://github.com/BimmerGestalt/AAIdrive/actions?query=workflow%3Abuild)
[![Code Coverage](https://img.shields.io/codecov/c/gh/BimmerGestalt/AAIdrive/main.svg)](https://codecov.io/gh/BimmerGestalt/AAIdrive)
[![Crowdin](https://badges.crowdin.net/androidautoidrive/localized.svg)](https://crowdin.com/project/androidautoidrive)
[![Release Download](https://img.shields.io/github/release/BimmerGestalt/AAIdrive.svg)](https://github.com/BimmerGestalt/AAIdrive/releases/latest)
[![Download Counter](https://img.shields.io/github/downloads/BimmerGestalt/AAIdrive/total.svg)](https://tooomm.github.io/github-release-stats/?username=BimmerGestalt&repository=AAIdrive)
[![Weekly Users](https://img.shields.io/endpoint?url=https://bimmergestalt.s3.amazonaws.com/aaidrive/usage/weekly_users.json)](https://bimmergestalt.s3.amazonaws.com/aaidrive/usage/car_report.html)
[![Gitter](https://badges.gitter.im/AndroidAutoIdrive/community.svg)](https://gitter.im/AndroidAutoIdrive/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
[![Buy Me A Coffee](https://img.shields.io/badge/support-buymeacoffee-5f7fff)](https://www.buymeacoffee.com/q4JVoxz)
![MIT Licensed](https://img.shields.io/github/license/BimmerGestalt/AAIdrive)

The BMW/Mini IDrive NBT does not offer native Android Auto integration, but does provide a very powerful Connected Apps convergence option with tight integration points into the car. This project is an effort to implement most of the features of Android Auto as unofficial BMW/Mini Connected Apps.

By relying on the Connected Apps technology, this app greatly extends the functionality of the car without any modifications or hacks. Any MY2014 or newer BMW or Mini equipped with NBT or NBT Evo and the "BMW Apps (6NR)" feature, an active [BMW ConnectedDrive subscription](https://bimmergestalt.github.io/AAIdrive/images/bmw-connected-subscription.png), or the "Mini Connected (SA6NM)" option should be compatible.

[![App List](docs/images/demo-applist.gif)
Gallery](https://bimmergestalt.github.io/AAIdrive/gallery.html)

Overview
--------

As part of the Connected Apps feature, when the phone connects to the car over USB (or Bluetooth in 2017+ models), enabled phone apps can show a special dashboard-optimized interface in the car.

AAIdrive, combined with the safety benefits of the tactile IDrive controller, builds on this protocol to allow the user to interact with their incoming notifications and control their phone's music while the phone is safely tucked away.

Getting Started
---------------

This app requires that the MyBMW or MINI app for your car is installed and that it can successfully enable your ID5+ car's [Apps checkbox](app/src/main/res/drawable/pic_btapp_bmw.jpg), or if your ID4 car has the [Connection Assistant option](app/src/main/res/drawable/pic_connassistant_bmw.jpg).

Download the APK of the latest stable release from the [Releases page](https://github.com/BimmerGestalt/AAIdrive/releases/latest). Choose the one that says "sentry" to automatically upload crash reports, or choose "nonalytics" otherwise. It is also available on the [Google Play Store](https://play.google.com/store/apps/details?id=me.hufman.androidautoidrive). After starting, the app should detect the MyBMW app and start waiting for the car connection.

Also consider trying out the nightly build! It has the latest features and is a preview of the next release, so please consider installing the [Sentry build](https://bimmergestalt.s3.amazonaws.com/aaidrive/builds/androidautoidrive-latest-main-mapbox-sentry-release.apk) to automatically report crashes.
The [nonalytics](https://bimmergestalt.s3.amazonaws.com/aaidrive/builds/androidautoidrive-latest-main-mapbox-nonalytics-release.apk) build is available too.

Check out the [FAQ](https://bimmergestalt.github.io/AAIdrive/faq.html) if you run into problems.

User Guide
----------

![Phone Connection](https://bimmergestalt.github.io/AAIdrive/images/screenshot-connection.png)

After connecting the phone to the car, the official MyBMW app should show this car icon in the status bar. When this icon appears, this app should connect and add its functionality to the car.

See [this guide](https://bimmergestalt.github.io/AAIdrive/connection.html) for tips on improving the connection reliability of the MyBMW app.

![Phone App List](https://bimmergestalt.github.io/AAIdrive/images/screenshot-phoneapps.jpg)

After all the apps are connected, a bunch of new entries will show up in the car's Connected menu. There should be a new Audioplayer or Spotify icon and a book icon with no label. This book icon is the Notifications app, if enabled.

![Music App List](https://bimmergestalt.github.io/AAIdrive/images/screenshot-medialist.jpg)

Several new entries will be added to the Media section of the control screen. The Audioplayer icon is the one with the main functionality, while the other displayed apps above the Audioplayer are quick shortcuts to switch playback to the respective apps. This screenshot also shows the legacy Spotify app at the bottom of the list.

Development Status
------------------

AAIdrive is feature-complete, implementing as many Android Auto features as are possible within the BMW app system, and several more. Beyond the occasional maintenance patch, this project is complete and won't see any more development.

Implemented Features
--------------------

  - Calendar integration
    - View the phone's calendar in the car
    - Automatically trigger the car's navigation to upcoming appointments
  - Car Information
    - Remembers fuel level, window status, and car's location after parking
    - Shows live-updating speed and compass while connected
    - Adds several pages of detailed car data to the infotainment screen
  - Car Navigation Integration
    - Android Navigation Intents and buttons can be handled by the connected car's navigation
    - Google Maps can share destinations to the connected car's navigation
    - Addresses can be entered in the phone interface to start the car's navigation
  - Google Assistant
    - Any voice assistant installed on the phone is added as a Connected App entry
    - Google Assistant works the best, but Alexa, Bixby, and Cortana are also compatible
    - The voice assistant app can be set as a hardware shortcut button for convenience
  - Phone Notifications
    - Popup about new notifications
    - Can play a notification sound through the car's speakers
    - Supports Dismiss, Mark As Read, or other notification actions
    - Supports replying, including emoji input
    - Reads out notifications using the car's TTS
  - Google Maps (proof-of-concept)
    - Basic search and routing
    - Includes some dark themes
    - Poor performance due to the nature of the protocol
    - Not compiled by default, because showing Google Maps in a car is against the Maps API license
  - Mapbox custom map
    - Search and routing, satellite imagery and traffic, 3d tilt and buildings
    - Supports custom Mapbox style urls
    - Poor performance over Bluetooth
  - Control of Android Auto compatible music apps
    - Supports browsing and searching apps' music libraries, including a special Spotify integration
    - Supports selecting from a list of currently-queued songs, as well as basic back/next control
    - Integrates into the car's audio context, for automatic resume and hardware button control
    - Supports the ID5+ music layout, enabling global coverart integration
    - Supports controlling any active music session, even apps that aren't Android Auto compatible
    - Automatically updates the screen to follow the active app
    - Recommended compatible apps:
      - Audiobooks and Podcasts:
        - [Acast Podcast Player](https://play.google.com/store/apps/details?id=com.acast.nativeapp)
        - [AntennaPod](https://play.google.com/store/apps/details?id=de.danoeh.antennapod)
        - [Audecibel](https://play.google.com/store/apps/details?id=com.podcastsapp)
        - [Blinkest](https://play.google.com/store/apps/details?id=com.blinkslabs.blinkist.android)
        - [The Bob & Tom Show](https://play.google.com/store/apps/details?id=com.radio.station.BOB.TOM)
        - [Castbox](https://play.google.com/store/apps/details?id=fm.castbox.audiobook.radio.podcast)
        - [Google Play Books](https://play.google.com/store/apps/details?id=com.google.android.apps.books)
        - [iVooz](https://play.google.com/store/apps/details?id=com.ivoox.app)
        - [Libro.fm Audiobooks](https://play.google.com/store/apps/details?id=fm.libro.librofm) up to version [3.2.2](https://apkpure.com/libro-fm-audiobooks/fm.libro.librofm/download/90-APK)
        - [Listen Audiobook Player](https://play.google.com/store/apps/details?id=com.acmeandroid.listen)
        - [Player FM](https://play.google.com/store/apps/details?id=fm.player)
        - [Podcast Addict](https://play.google.com/store/apps/details?id=com.bambuna.podcastaddict)
        - [Podcast Republic](https://play.google.com/store/apps/details?id=com.itunestoppodcastplayer.app)
        - [Stitcher](https://play.google.com/store/apps/details?id=com.stitcher.app)
        - [Voice Audiobook Player](https://play.google.com/store/apps/details?id=de.ph1b.audiobook)
      - Music Library
        - [AIMP](https://play.google.com/store/apps/details?id=com.aimp.player)
        - [Black Player](https://play.google.com/store/apps/details?id=com.musicplayer.blackplayerfree)
        - [DSub](https://play.google.com/store/apps/details?id=github.daneren2005.dsub)
        - [HiBy Music](https://play.google.com/store/apps/details?id=com.hiby.music)
        - [jetAudio HD](https://play.google.com/store/apps/details?id=com.jetappfactory.jetaudio)
        - [Media Monkey](https://play.google.com/store/apps/details?id=com.ventismedia.android.mediamonkey)
        - [Musicolet Music Player](https://play.google.com/store/apps/details?id=in.krosbits.musicolet)
        - [Neutron Music Player](https://play.google.com/store/apps/details?id=com.neutroncode.mp)
        - [Plex](https://play.google.com/store/apps/details?id=com.plexapp.android) (only music and podcasts)
        - [PlayerPro](https://play.google.com/store/apps/details?id=com.tbig.playerprotrial)
        - [PowerAmp](https://play.google.com/store/apps/details?id=com.maxmpz.audioplayer)
        - [Retro Music Player](https://play.google.com/store/apps/details?id=code.name.monkey.retromusic)
        - [Rocket Player](https://play.google.com/store/apps/details?id=com.jrtstudio.AnotherMusicPlayer)
        - [Symfonium](https://play.google.com/store/apps/details?id=app.symfonik.music.player)
        - [TimberX Music Player](https://play.google.com/store/apps/details?id=com.naman14.timberx)
        - [VLC For Android](https://play.google.com/store/apps/details?id=org.videolan.vlc)
      - Radio
        - [AP News](https://play.google.com/store/apps/details?id=mnn.Android)
        - [Antenne Bayern](https://play.google.com/store/apps/details?id=de.antenne.android)
        - [ARD Audiothek](https://play.google.com/store/apps/details?id=de.ard.audiothek)
        - [Audials Radio](https://play.google.com/store/apps/details?id=com.audials)
        - [BFM](https://play.google.com/store/apps/details?id=my.bfm.app)
        - [Dash Radio](https://play.google.com/store/apps/details?id=com.dashradio.dash)
        - [DI.FM](https://play.google.com/store/apps/details?id=com.audioaddict.di)
        - [Energy Radio](https://play.google.com/store/apps/details?id=radioenergy.app)
        - [Guardian](https://play.google.com/store/apps/details?id=com.guardian)
        - [HOT97 Official](https://play.google.com/store/apps/details?id=com.jacapps.whhl)
        - [Manchester United](https://play.google.com/store/apps/details?id=com.mu.muclubapp)
        - [myTuner](https://play.google.com/store/apps/details?id=com.appgeneration.itunerfree)
        - [Nederland.FM](https://play.google.com/store/apps/details?id=nl.nibbixsoft.app)
        - [NHL](https://play.google.com/store/apps/details?id=com.nhl.gc1112.free)
        - [ntv Nachrichten](https://play.google.com/store/apps/details?id=de.lineas.lit.ntv.android)
        - [NYTimes](https://play.google.com/store/apps/details?id=com.nytimes.android)
        - [Open Radio](https://play.google.com/store/apps/details?id=com.yuriy.openradio)
        - [R101](https://play.google.com/store/apps/details?id=it.r101)
        - [Radio 105](https://play.google.com/store/apps/details?id=it.froggy.android.radio105)
        - [Radio Bob](https://play.google.com/store/apps/details?id=de.radiobob.radio)
        - [Radio FM](https://play.google.com/store/apps/details?id=com.radio.fmradio)
        - [Radio Monte Carlo](https://play.google.com/store/apps/details?id=it.froggy.android.rmc)
        - [Radio Nowy Swiat](https://play.google.com/store/apps/details?id=com.thehouseofcode.radio_nowy_swiat)
        - [Replaio FM Radio](https://play.google.com/store/apps/details?id=com.hv.replaio)
        - [RTL 102.5](https://play.google.com/store/apps/details?id=com.rtl.rtlapp)
        - [Scanner Radio](https://play.google.com/store/apps/details?id=com.scannerradio)
        - [SiriusXM](https://play.google.com/store/apps/details?id=com.sirius)
        - [Simple Radio](https://play.google.com/store/apps/details?id=com.streema.simpleradio)
        - [SomaFM](https://play.google.com/store/apps/details?id=com.dgmltn.radiomg.somafm)
        - [SWR3](https://play.google.com/store/apps/details?id=de.swr.swr3radio)
        - [sunshine live](https://play.google.com/store/apps/details?id=app.sunshinelive.de.sunshinelive)
        - [Versuz Radio](https://play.google.com/store/apps/details?id=com.versuzradio)
        - [Virgin Radio Italy](https://play.google.com/store/apps/details?id=it.froggy.android.virginradio)
      - Streaming Services
        - [Apple Music](https://play.google.com/store/apps/details?id=com.apple.android.music)
        - [Anghami](https://play.google.com/store/apps/details?id=com.anghami)
        - [Gaana Music](https://play.google.com/store/apps/details?id=com.gaana)
        - [JioSaavn](https://play.google.com/store/apps/details?id=com.jio.media.jiobeats)
        - [Qobuz](https://play.google.com/store/apps/details?id=com.qobuz.music)
        - [SoundCloud](https://play.google.com/store/apps/details?id=com.soundcloud.android)
        - [Spotify](https://play.google.com/store/apps/details?id=com.spotify.music)
        - [Tidal](https://play.google.com/store/apps/details?id=com.aspiro.tidal)

Integration Points
------------------

Besides showing a self-contained remote UI, the IDrive system offers many exciting integration points. Here are a few that this project supports:

  - The UI widgets automatically take on the respective theme to fit the car
  - The Assistants, Map View, Notification List, and Music Playback screens can be assigned to the physical shortcut buttons in the dashboard
  - Car information is retained after disconnect, such as window status and parked location
  - New notifications trigger a statusbar icon
  - New notifications can trigger a popup
  - New notification popups can be disabled if a passenger is detected in the seat
  - Notifications can be read out by the car's TTS when received or when selected
  - The car's navigation system is available to handle Android Navigation Intents
  - The car's location and heading is shown in the custom map
  - The currently-playing app is displayed along the top of the IDrive screen
  - The currently-playing song title is shown in the IDrive4 Multimedia side panel
  - The currently-playing song coverart and progress is shown in the IDrive5+ Home screen and Multimedia side panel
  - On a MY2017+ car supporting Bluetooth Apps, audio focus will be enabled which grants the following extra features:
    - The Media shortcut button opens this app when it is in control of the music
    - Automatically resumes playback when reconnecting to the car
    - Playback pauses when pushing the mute button or during calls
    - The physical back/next buttons can be held down to seek within a track or pressed to skip tracks
    - The steering wheel controls can skip tracks from the instrument cluster
    - Enqueued songs can be scrolled in the instrument cluster, depending on app support

Limitations
-----------

This project replicates some of the features of Android Auto using the IDrive interface, using the same APIs that Android Auto uses to talk to the music apps. It cannot currently provide more advanced Android Auto features, such as:

  - Integration with the car's Voice Assistant button
  - Screen-casting of arbitrary phone apps to the car (Google Maps, Waze, or any other apps)
  - Displaying the original Android Auto interface at all

Due to the unofficial reverse-engineered nature of this project, it has some limitations:

  - The main menu entries' icons and text can't be altered, and so do not look exactly correct
  - The individual music source icons sometimes don't open the Audioplayer interface in ID4, but they do switch the active music source
  - Android Oreo disabled Android Open Accessory Protocol 2 audio output, which is required to play audio over the app's USB connection in model years 2014-2017. Please listen over Bluetooth audio and use this app as a control interface.
  - Some Android Auto music apps enforce a list of allowed client apps, preventing this app from launching them or browsing their libraries. However, once they are running, they can be controlled. For example, these popular music apps can not be launched, they must be started manually:
    - Amazon Music
    - Audible
    - Bandcamp
    - CloudPlayer
    - Deezer
    - doubleTwist
    - Google Play Music
    - iHeartAuto
    - TuneIn Radio
    - Pandora
    - Scribd
    - Smart Audiobook Player
    - YouTube Music

Requirements
------------

To communicate to the car, this project relies on the proxy connection that is created by the main MyBMW or Mini app on the phone. Additionally, the legacy Connected and the Connected Classic apps have been tested as compatible for this purpose, but the Connected app is more resilient against Android's memory management.

Developer Guide
---------------

To build your own test versions of the app and help contribute to the project, follow [this Developer Guide](https://bimmergestalt.github.io/AAIdrive/developers) to set up your development environment.

Privacy
-------

This project contains no advertising or user tracking, and is developed entirely for fun and to enhance the usefulness of the BMW/Mini infotainment system.

The app uses the Internet Permission to make a TCP connection to the car, which is reachable through a localhost socket on the main Connected app. Additionally, some cover art and incoming picture notifications (such as from Hangouts) may be fetched from Internet URLs. No other Internet access is required for the app's functionality.

As part of its functionality, the app collects and remembers some information locally on your phone:

  - The Car Information tab remembers information about the most-recently-connected car, including model and available features, specific driving statistics and vehicle settings, and the last location reported by the car while it was connected
  - The music functionality remembers a list of installed music apps and what features they provide
  - The Spotify integration retains a token to access your Spotify Library

The app also needs some other information to function, but does not remember any of it and will never share it:

  - To establish the car connection, the app identifies which BMW and Mini apps are installed
  - The app watches Bluetooth connections to identify when the car is connected
  - Any installed Voice Assistants are discovered to be added to the car
  - Apps which act as AAIdrive Addons are discovered and presented in the Addons tab
  - If enabled, notifications are read from the phone while connected to the car and then forgotten when disconnected
  - If compiled into the app and then enabled, the custom map feature will use the car or phone's location while displaying the map

The analytics-disabled version will never share any information, and no analytics code is compiled into this version of the app.
The analytics-enabled version provides an option to share some anonymized information to [Sentry](https://www.sentry.io) to assist with debugging and development: If enabled, besides any rare and unfortunate crashes, the app will share any [installed music apps](app/src/sentry/java/me/hufman/androidautoidrive/Analytics.kt) and the capabilities each app provides, as well as the [model and capabilities](app/src/main/java/me/hufman/androidautoidrive/CarInformationDiscovery.kt#L36) of any connected car for usage statistics and feature prioritization.

Each release provides both an analytics-enabled and analytics-disabled option.

  Example Analytics Data

  ### Music App
```
{
  "appId": "github.daneren2005.dsub",
  "appName": "DSub",
  "controllable": "false",
  "connectable": "true",
  "browseable": "true",
  "searchable": "false",
  "playsearchable": "false"
}
```

  ### Car Connection
```
{
  "a4axl": "true",
  "alignment_right": "true",
  "hmi_display_height": "480",
  "hmi_display_width": "1280",
  "hmi_role": "HU",
  "hmi_type": "MINI ID5",
  "hmi_version": "EntryEvo_ID5_1903_Release ID5_1903-490-1837K Build 47 - Rev:203015 2018-11-14 08:39:42",
  "inbox": "true",
  "map": "true",
  "navi": "true",
  "pia": "true",
  "speech2text": "true",
  "speedlock": "true",
  "touch_command": "false",
  "tts": "true",
  "vehicle_country": "US",
  "vehicle_productiondate": "03.00",
  "vehicle_type": "F56",
  "voice": "false"
}
```


# BoardGameWork
<!--[![Code Style](https://github.com/tudo-aqua/bgw-core/actions/workflows/code-style.yml/badge.svg)](https://github.com/tudo-aqua/bgw/security/code-scanning)-->
[![Build](https://github.com/tudo-aqua/bgw-core/actions/workflows/analyze-build-deploy.yml/badge.svg)](https://github.com/tudo-aqua/bgw-core/actions)
[![GitHub-Pages](https://github.com/tudo-aqua/bgw-core/actions/workflows/github-pages.yml/badge.svg)](https://tudo-aqua.github.io/bgw/)

[![Maven Central](https://img.shields.io/maven-central/v/tools.aqua/bgw-gui?label=MavenCentral%20bgw-gui&logo=apache-maven)](https://search.maven.org/artifact/tools.aqua/bgw-gui)
[![Maven Central](https://img.shields.io/maven-central/v/tools.aqua/bgw-gui?label=MavenCentral%20bgw-net-common&logo=apache-maven)](https://search.maven.org/artifact/tools.aqua/bgw-net-common)
[![Maven Central](https://img.shields.io/maven-central/v/tools.aqua/bgw-gui?label=MavenCentral%20bgw-net-client&logo=apache-maven)](https://search.maven.org/artifact/tools.aqua/bgw-net-client)
[![Maven Central](https://img.shields.io/maven-central/v/tools.aqua/bgw-gui?label=MavenCentral%20bgw-net-server&logo=apache-maven)](https://search.maven.org/artifact/tools.aqua/bgw-net-server)

[![KDocs BGW-Gui](https://img.shields.io/static/v1?label=kDoc%20bgw-gui&message=overview&color=blue)](https://tudo-aqua.github.io/bgw/bgw-gui-kdoc/index.html)
[![KDocs BGW-Gui](https://img.shields.io/static/v1?label=kDoc%20bgw-net-common&message=overview&color=blue)](https://tudo-aqua.github.io/bgw/bgw-net-common-kdoc/index.html)
[![KDocs BGW-Gui](https://img.shields.io/static/v1?label=kDoc%20bgw-net-client&message=overview&color=blue)](https://tudo-aqua.github.io/bgw/bgw-net-client-kdoc/index.html)
------------

BoardGameWork is a framework for creating 2D board game applications.

Read on [how to get started](https://tudo-aqua.github.io/bgw/), or take a look at the complete API documentation for [bgw-gui](https://tudo-aqua.github.io/bgw/bgw-gui-kdoc/index.html), [bgw-net-common](https://tudo-aqua.github.io/bgw/bgw-net-common-kdoc/index.html), or [bgw-net-client](https://tudo-aqua.github.io/bgw/bgw-net-client-kdoc/index.html).

Examples are available for [MauMau](https://github.com/tudo-aqua/bgw/tree/main/bgw-examples/bgw-maumau-example), [Sudoku](https://github.com/tudo-aqua/bgw/tree/main/bgw-examples/bgw-sudoku-example) and [Tetris](https://github.com/tudo-aqua/bgw/tree/main/bgw-examples/bgw-tetris-example).

<!-- GETTING STARTED -->

## Getting Started

### Prerequisites

<!-- https://www.azul.com/downloads/?version=java-11-lts&package=jdk-fx#download-openjdk -->

BoardGameWork is built on top of [JavaFX 17](https://openjfx.io/openjfx-docs/) and therefore requires at least JDK 11. Since JavaFX was decoupled from the JavaJDK as of JDK 11, BoardGameWork comes with JavaFX dependencies including their native libraries for various platforms like Windows, Linux and Mac.

We recommend installing a JDK build that already includes JavaFX to ensure your platform is supported. [Azul Zulu Builds of OpenJDK](https://www.azul.com/downloads/?version=java-11-lts&package=jdk-fx#download-openjdk) support a wide range of platforms and architectures including [Mac M1](https://www.azul.com/downloads/?version=java-11-lts&os=macos&architecture=arm-64-bit&package=jdk-fx#download-openjdk).

### Setup

Start by adding the latest version of BGW as a dependency to your project.

#### Gradle
```gradle
implementation("tools.aqua:bgw-gui:0.9")
```

#### Maven
```xml
<dependency>
  <groupId>tools.aqua</groupId>
  <artifactId>bgw-gui</artifactId>
  <version>0.9</version>
</dependency>
```

You also need to specify the correct JVM target in your build system.

#### Gradle
```gradle
compileKotlin {
    kotlinOptions.jvmTarget = "11"
}
```

#### Maven
```xml
<configuration>
    <jvmTarget>11</jvmTarget>
</configuration>
```


[![Android CI with Gradle](https://github.com/opensrp/fhircore/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/opensrp/fhircore/actions/workflows/ci.yml?query=branch%3Amain)
[![Codecov Test Coverage](https://codecov.io/gh/opensrp/fhircore/branch/main/graph/badge.svg?token=IJUTHZUGGH)](https://codecov.io/gh/opensrp/fhircore)
[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
[![Zulip Chat](https://img.shields.io/badge/zulip-join_chat-brightgreen.svg)](https://chat.fhir.org/#narrow/stream/370552-OpenSRP)
[![Slack Chat](https://img.shields.io/badge/slack-join_chat-purple)](https://join.slack.com/t/opensrp/shared_invite/zt-1xvw5fsjo-5RPlKqHmpU57SumJavgCzA)

# OpenSRP FHIR Core

FHIR Core is a Kotlin application for delivering offline-capable, mobile-first healthcare project implementations from local community to national and international scale using FHIR and the WHO Smart Guidelines on Android.

FHIR Core is architected as a FHIR native digital health platform powered by Google's [Android FHIR SDK](https://github.com/google/android-fhir) and [HAPI FHIR](https://hapifhir.io/). FHIR Core's user experience and module oriented design are based on over a decade of real world experience implementing digital health projects with [OpenSRP](https://smartregister.org/). This repository contains the Android mobile application built to:

- load configuration data as FHIR resources,
- support the WHO Smart Guidelines,
- manage the identities of healthcare workers (HCWs), community health workers (CHWs), care teams, patients, and clients,
- collect, view, and edit healthcare data with dynamic forms using FHIR's [Structured Data Capture](https://hl7.org/fhir/us/sdc/index.html) (SDC) implementation,
- securely store healthcare data encrypted at rest and securely transmit healthcare data using TLS,
- manage location hierarchies defined by community to national and international administrative boundaries.

For remote data storage and login, the mobile application requires:
- a [Keycloak](https://www.keycloak.org/) server to manage identity, authentication, and authorization;
- a [HAPI FHIR](https://hapifhir.io/) server to store operation and configuration data that includes the [HAPI FHIR to Keycloak integration](https://github.com/opensrp/hapi-fhir-keycloak).

FHIRcore also interoperates well with:
- [OpenSRP Web](https://github.com/OpenSRP/web) to access healthcare data from the same HAPI FHIR server.

<img align=center width=400 src="static/img/fhircore.png">

## Getting Started

Due to it's dependency on the Android FHIR SDK's workflow library, OpenSRP FHIR Core requires a minimum Android SDK version of Android 8.0 (API level 26).

This repository contains the folders
* **[android](android)**: for building the Android application.
* **[docs](docs)**: a library of documents describing the FHIR Core solution.

We recommend reviewing the [docs](https://docs.smartregister.org/) before setting up the Android Studio Project in the [android](android) folder.

For starter resources on the FHIR specification:

1. [Intro to FHIR](https://youtu.be/YbQcJj1GqH0) - By James Agnew of Smile CDR
1. [FHIR resource list](http://hl7.org/fhir/resourcelist.html)

For starter resources on the Android FHIR SDK and this repo:

1. Android FHIR SDK Demo - [Link](https://drive.google.com/file/d/1ORjk3pNOKjGyZlbayAViPy4xkI8p-aFB/view?usp=sharing)
1. Android FHIR SDK Intro Slide deck - [Link](https://docs.google.com/presentation/d/1oc6EBJAcXsBwyBgtnra61xoM7naBF0aj8WbfrUT7Y2A)
1. FHIR Core Intro slide deck - [Link](https://docs.google.com/presentation/d/1eFsf9a5dcNqKXlfsEWyNZyoVooIbK3jq6694xarARr8)