diff --git a/charts/.gitignore b/charts/.gitignore
new file mode 100644
index 0000000..42afabf
--- /dev/null
+++ b/charts/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/charts/README.md b/charts/README.md
new file mode 100644
index 0000000..624acfa
--- /dev/null
+++ b/charts/README.md
@@ -0,0 +1,3 @@
+# Dzeio Charts
+
+Originally from https://github.com/HackPlan/AndroidCharts but We wanted more options :D
diff --git a/charts/build.gradle b/charts/build.gradle
new file mode 100644
index 0000000..75a307e
--- /dev/null
+++ b/charts/build.gradle
@@ -0,0 +1,40 @@
+plugins {
+ id 'com.android.library'
+ id 'org.jetbrains.kotlin.android'
+}
+
+android {
+ compileSdk 32
+
+ defaultConfig {
+ minSdk 21
+ targetSdk 32
+
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ consumerProguardFiles "consumer-rules.pro"
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_6
+ targetCompatibility JavaVersion.VERSION_1_6
+ }
+ kotlinOptions {
+ jvmTarget = '1.6'
+ }
+}
+
+dependencies {
+
+ implementation 'androidx.core:core-ktx:1.7.0'
+ implementation 'androidx.appcompat:appcompat:1.4.2'
+ implementation 'com.google.android.material:material:1.6.1'
+ testImplementation 'junit:junit:4.13.2'
+ androidTestImplementation 'androidx.test.ext:junit:1.1.3'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
+}
diff --git a/charts/consumer-rules.pro b/charts/consumer-rules.pro
new file mode 100644
index 0000000..e69de29
diff --git a/charts/proguard-rules.pro b/charts/proguard-rules.pro
new file mode 100644
index 0000000..481bb43
--- /dev/null
+++ b/charts/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/charts/src/androidTest/java/com/dzeio/charts/ExampleInstrumentedTest.kt b/charts/src/androidTest/java/com/dzeio/charts/ExampleInstrumentedTest.kt
new file mode 100644
index 0000000..ae841cb
--- /dev/null
+++ b/charts/src/androidTest/java/com/dzeio/charts/ExampleInstrumentedTest.kt
@@ -0,0 +1,24 @@
+package com.dzeio.charts
+
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.ext.junit.runners.AndroidJUnit4
+
+import org.junit.Test
+import org.junit.runner.RunWith
+
+import org.junit.Assert.*
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+@RunWith(AndroidJUnit4::class)
+class ExampleInstrumentedTest {
+ @Test
+ fun useAppContext() {
+ // Context of the app under test.
+ val appContext = InstrumentationRegistry.getInstrumentation().targetContext
+ assertEquals("com.dzeio.charts.test", appContext.packageName)
+ }
+}
diff --git a/charts/src/main/AndroidManifest.xml b/charts/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..e47d5d6
--- /dev/null
+++ b/charts/src/main/AndroidManifest.xml
@@ -0,0 +1,5 @@
+
+
+
+
diff --git a/charts/src/main/java/com/dzeio/charts/BarView.kt b/charts/src/main/java/com/dzeio/charts/BarView.kt
new file mode 100644
index 0000000..a397137
--- /dev/null
+++ b/charts/src/main/java/com/dzeio/charts/BarView.kt
@@ -0,0 +1,199 @@
+package com.dzeio.charts
+
+import android.content.Context
+import android.graphics.Canvas
+import android.graphics.Color
+import android.graphics.Paint
+import android.graphics.Rect
+import android.util.AttributeSet
+import android.util.Log
+import android.view.View
+import kotlin.math.abs
+
+class BarView @JvmOverloads constructor(context: Context?, attrs: AttributeSet? = null) :
+ View(context, attrs) {
+
+ companion object {
+ const val TAG = "DzeioCharts/BarView"
+ }
+
+ /**
+ * Nunber of entries displayed at the same time
+ */
+ val numberOfEntries = 5
+
+ /**
+ * Number of labels displayed at the same time
+ */
+ val numberOfLabels = 3
+
+ /**
+ * Spacing between entries
+ */
+ val spacing = 22
+
+ /**
+ * top margin from the canvas
+ */
+ @Deprecated("Not needed anymore, Use the parent Padding/Margin")
+ private val topMargin: Int = 5
+
+ private val textTopMargin = 5
+
+ private var barWidth: Int = 0
+
+ private val textColor = Color.parseColor("#9B9A9B")
+
+ private val foregroundColor = Color.parseColor("#FC496D")
+ private val percentList: ArrayList = ArrayList()
+ private var targetPercentList: ArrayList = ArrayList()
+ private val textPaint: Paint = Paint().also {
+ it.isAntiAlias = true
+ it.color = textColor
+ it.textSize = 25f
+ it.textAlign = Paint.Align.CENTER
+ }
+
+ private val fgPaint: Paint = Paint().also {
+ it.isAntiAlias = true
+ it.color = foregroundColor
+ }
+ private val rect: Rect = Rect()
+ private var bottomTextDescent = 0
+ private var bottomTextHeight = 0
+ private var bottomTextList: ArrayList? = ArrayList()
+ private val animator: Runnable = object : Runnable {
+ override fun run() {
+ var needNewFrame = false
+ for (i in targetPercentList.indices) {
+ if (percentList[i] < targetPercentList[i]) {
+ percentList[i] = percentList[i] + 0.02f
+ needNewFrame = true
+ } else if (percentList[i] > targetPercentList[i]) {
+ percentList[i] = percentList[i] - 0.02f
+ needNewFrame = true
+ }
+ if (abs(targetPercentList[i] - percentList[i]) < 0.02f) {
+ percentList[i] = targetPercentList[i]
+ }
+ }
+ if (needNewFrame) {
+ postDelayed(this, 20)
+ }
+ invalidate()
+ }
+ }
+
+ /**
+ * dataList will be reset when called is method.
+ *
+ * @param bottomStringList The String ArrayList in the bottom.
+ */
+ fun setBottomTextList(bottomStringList: ArrayList?) {
+ barWidth = measuredWidth / numberOfEntries - spacing
+ bottomTextList = bottomStringList
+ val r = Rect()
+ bottomTextDescent = 0
+ for (s in bottomTextList!!) {
+ textPaint.getTextBounds(s, 0, s.length, r)
+ if (bottomTextHeight < r.height()) {
+ bottomTextHeight = r.height()
+ }
+ Log.d(TAG, measuredWidth.toString())
+// if (autoSetWidth && barWidth < r.width()) {
+// barWidth = r.width()
+// }
+ if (bottomTextDescent < abs(r.bottom)) {
+ bottomTextDescent = abs(r.bottom)
+ }
+ }
+ postInvalidate()
+ }
+
+ /**
+ * @param list The ArrayList of Integer with the range of [0-max].
+ */
+ fun setDataList(list: ArrayList) {
+ barWidth = measuredWidth / numberOfEntries - spacing
+ // Calculate max
+ val max = list.reduce { acc, i -> if (acc > i) return@reduce acc else return@reduce i }
+
+ targetPercentList = ArrayList()
+ for (integer in list) {
+ targetPercentList.add(1 - integer.toFloat() / max.toFloat())
+ }
+
+ // Make sure percentList.size() == targetPercentList.size()
+ if (percentList.isEmpty() || percentList.size < targetPercentList.size) {
+ val temp = targetPercentList.size - percentList.size
+ for (i in 0 until temp) {
+ percentList.add(1f)
+ }
+ } else if (percentList.size > targetPercentList.size) {
+ val temp = percentList.size - targetPercentList.size
+ for (i in 0 until temp) {
+ percentList.removeAt(percentList.size - 1)
+ }
+ }
+
+ removeCallbacks(animator)
+ post(animator)
+ }
+
+ override fun onDraw(canvas: Canvas) {
+ if (percentList.isNotEmpty()) {
+ for (i in 1 until percentList.size) {
+ val left = spacing * i + barWidth * (i - 1)
+ Log.d(TAG, "$spacing, $i, $barWidth = $left")
+ val right = (spacing + barWidth) * i
+ val bottom = height - bottomTextHeight - textTopMargin
+ val top = topMargin + ((bottom - topMargin) * percentList[i - 1])
+
+ rect.set(left, top.toInt(), right, bottom)
+
+ canvas.drawRect(rect, fgPaint)
+ }
+ }
+ if (bottomTextList != null && !bottomTextList!!.isEmpty()) {
+ var i = 1
+ for (s in bottomTextList!!) {
+ canvas.drawText(
+ s,
+ (spacing * i + barWidth * (i - 1) + barWidth / 2).toFloat(),
+ (height - bottomTextDescent).toFloat(),
+ textPaint
+ )
+ i++
+ }
+ }
+ }
+
+ override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
+ val mViewWidth = measureWidth(widthMeasureSpec)
+ val mViewHeight = measureHeight(heightMeasureSpec)
+ setMeasuredDimension(mViewWidth, mViewHeight)
+ }
+
+ private fun measureWidth(measureSpec: Int): Int {
+ var preferred = 0
+ if (bottomTextList != null) {
+ preferred = bottomTextList!!.size * (barWidth + spacing)
+ }
+ return getMeasurement(measureSpec, preferred)
+ }
+
+ private fun measureHeight(measureSpec: Int): Int {
+ val preferred = 222
+ return getMeasurement(measureSpec, preferred)
+ }
+
+ private fun getMeasurement(measureSpec: Int, preferred: Int): Int {
+ val specSize = MeasureSpec.getSize(measureSpec)
+ val measurement = when (MeasureSpec.getMode(measureSpec)) {
+ MeasureSpec.EXACTLY -> specSize
+ MeasureSpec.AT_MOST -> Math.min(preferred, specSize)
+ else -> preferred
+ }
+ return measurement
+ }
+}
diff --git a/charts/src/test/java/com/dzeio/charts/ExampleUnitTest.kt b/charts/src/test/java/com/dzeio/charts/ExampleUnitTest.kt
new file mode 100644
index 0000000..cf39879
--- /dev/null
+++ b/charts/src/test/java/com/dzeio/charts/ExampleUnitTest.kt
@@ -0,0 +1,17 @@
+package com.dzeio.charts
+
+import org.junit.Test
+
+import org.junit.Assert.*
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+class ExampleUnitTest {
+ @Test
+ fun addition_isCorrect() {
+ assertEquals(4, 2 + 2)
+ }
+}
diff --git a/settings.gradle b/settings.gradle
index b83db14..367a633 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -15,4 +15,6 @@ dependencyResolutionManagement {
}
}
rootProject.name = "OpenHealth"
+
include ':app'
+include ':charts'