B4A Library MPAndroidCharts - Various type of graphs / charts (Latest library V1.22 in post #1)

Johan Schoeman

Expert
Licensed User
Longtime User
This library is awesome!!
I was wondering is there any way we can find the points where the line "cuts" the x axis? (the y is relatively easy by calculating the point with x=0)
No, you will have to determine that from the data that you are passing to the library to draw the graph. Perhaps a bit of linear interpolation might do it....
 

Johan Schoeman

Expert
Licensed User
Longtime User
No, the library expects the same number of points for all series to be passed. The combined line chart and bar chart might perhaps be a "cleaner" solution as you won't see the bars with a value of 0.
 

Paulsche

Well-Known Member
Licensed User
Longtime User

a combinated (multi bar charts and line charts) would be nice !
 

Paulsche

Well-Known Member
Licensed User
Longtime User
I want to embed the chart graphic in a PDF, how do I get a bitmap graphics?
 

Johan Schoeman

Expert
Licensed User
Longtime User
a combinated (multi bar charts and line charts) would be nice !
The original Github project does not support Multi Line and Multi Bar in the same project. But I think I have found a workaround to do at least 1 x Bar with multiple Lines charts. Still need to do it and will then post it if it works.
 

Johan Schoeman

Expert
Licensed User
Longtime User
I want to embed the chart graphic in a PDF, how do I get a bitmap graphics?
There are 2 x methods in the original Github project that will save the graphs to bitmaps. I will add them to the wrappers and then post the new library
 

Johan Schoeman

Expert
Licensed User
Longtime User
I want to embed the chart graphic in a PDF, how do I get a bitmap graphics?
OK - here we go. Posting new library files and B4A project demonstrating the "save"" and bitmap options.

Take note of the following permission that was added to the B4A manifest in the attached B4A project:
AddPermission(android.permission.WRITE_EXTERNAL_STORAGE)

The following options are added:
1. Files will be stored in the Gallery which seems to have the DCIM folder as it's parent folder
mlc1.saveToGallery("mygraph", 50)
2. Files will be stored in the folder that you specify starting from the root folder of your device - see the pop-up help when using this method
mlc1.saveToPath("mygraph","")

3. Return a Bitmap to the B4A project - do with it whatever you require to do with the bitmap in your B4A project

Also note the timer that I have added. It gives the library time to complete drawing the graph(s) before we attempt a "save". Else an error will occur (error = bitmap height and bitmap width needs to be > 0).

The attached pic is of the bitmap that I have returned from the library to the B4A project. Have added an option to set the background color (i.e color around the outer edge of the graph) when the graph is saved or for the bitmap being returned.




B4X:
#Region  Project Attributes
    #ApplicationLabel: MPMultiLineChartV3
    #VersionCode: 3
    #VersionName:
    'SupportedOrientations possible values: unspecified, landscape or portrait.
    #SupportedOrientations: landscape
    #CanInstallToExternalStorage: False
#End Region

#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: True
#End Region

Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.
  
    Dim t As Timer

End Sub

Sub Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.

    Private mlc1  As MultiLineChart
    Private Button1 As Button
    Dim flag As Int = 0

    Private ImageView1 As ImageView
End Sub

Sub Activity_Create(FirstTime As Boolean)
    'Do not forget to load the layout file created with the visual designer. For example:
    Activity.LoadLayout("main")
  
  
    t.Initialize("t",10000)
    ImageView1.Visible = False

  
    mlc1.ChartDescription = "TITLE : Just some random data"   'SORTED OUT DISPLAY OF DESCRIPTION IF NO TITLE IS SET - 22 OCT 2015
    mlc1.ChartDescriptionColor = Colors.Red
    mlc1.ChartDescriptionTextSize = 15  
    mlc1.GridBackgroundColor = Colors.DarkGray
  
'    RIGHT_OF_CHART, RIGHT_OF_CHART_CENTER, RIGHT_OF_CHART_INSIDE,
'    LEFT_OF_CHART, LEFT_OF_CHART_CENTER, LEFT_OF_CHART_INSIDE,
'    BELOW_CHART_LEFT, BELOW_CHART_RIGHT, BELOW_CHART_CENTER,

'   CIRCLE, SQUARE, LINE

    mlc1.LegendShapeSize = 10.0
    mlc1.setTheLegendPositionAndForm("BELOW_CHART_CENTER","CIRCLE")
    mlc1.TheLegendColor = Colors.yellow
    mlc1.TheLegendTextSize = 10.0  
    mlc1.LegendText = Array As String("2011", "2012", "2013", "2014", "2015")


    mlc1.ValueTextColor = Array As Int(Colors.White, Colors.Red, Colors.White, Colors.Red, Colors.White)
    mlc1.ValueTextSize = Array As Float(12.0, 10.0, 14.0, 8.0, 16.0)

    mlc1.YaxisTextSize = 10.0
  
'   We are going to draw 5 charts/graphs
    mlc1.Chart_1_Data = Array As Float(10.0, 30.0, 20.0, -50.0, 40.0, -30.0, 45.0, -15.0, 38.3, -18.9, 29.8, -15.7)
    mlc1.Chart_2_Data = Array As Float(1200.0, 750.0, 450.0, 960.0, 730.0, 1100.0, 676.5, 985.6, 1010.8, 836.4, 498.5, 965.3)  
    mlc1.Chart_3_Data = Array As Float(-10.0, -30.0, -20.0, 50.0, -40.0, 30.0, -45.0, 15.0, -38.3, 18.9, -29.8, 15.7)  
    mlc1.Chart_4_Data = Array As Float(345.0, -380.2, -250.4, 849.7, 445.0, 600.5, -300.0, 50.0, 550.0, 1100.0, 894.2, 993.8)  
    mlc1.Chart_5_Data = Array As Float(40.0, 60.0, 50.0, -80.0, 70.0, -60, 75.0, -45.0, 68.3, -48.9, 59.8, -45.7)  
  
    Dim ad() As String = Array As String("RIGHT", "LEFT", "RIGHT", "LEFT", "RIGHT")     'NEW - ADDED Y AXIS DEPENDANCY - 22 OCT 2015
    mlc1.YaxisDependancy = ad                                                           'NEW - ADDED Y AXIS DEPENDANCY - 22 OCT 2015

    mlc1.DrawGraphValues = Array As Boolean(True, True, True, True, True)  
    mlc1.MaxVisibleValueCount = 20
  
  
'   Maximum 5 colors to be passed ==> must be at least equal to the number of data sets that are passed i.e maximum 5
'   If you pass only for eg 2 data sets then at least 2 colors need to be passed
'   If more that 2 colors are passed with for eg only 2 data sets then only the first 2 colors will be used in the color array
    mlc1.LineColors = Array As Int(Colors.Yellow, Colors.Red, Colors.Blue, Colors.Green, Colors.Cyan)
    mlc1.GraphLineWidth = Array As Float(2.0, 3.0, 4.0, 5.0, 6.0)
    mlc1.DrawFilled = Array As Boolean(False, False, False, False, False)
  
    mlc1.XaxisTextColor = Colors.Green
    mlc1.XaxisTextSize = 12.0  
    mlc1.XaxisLables = Array As String("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec")
'  TOP, BOTTOM, BOTH_SIDED, TOP_INSIDE, BOTTOM_INSIDE
    mlc1.XaxisLabelPosition = "BOTTOM"
    mlc1.XaxisTextAngle = 30                          'NEW - 'AMENDED CODE TO SET THE ANGLE OF THE X AXIS LABELS BETWEEN -90 and 90 - 22 OCT 2015
    mlc1.VerticalGridColor = Colors.Green             'NEW  - ADDED ABILITY TO SET THIS COLOR - 22 OCT 2015

    mlc1.DrawXaxisGridLines = True
  
    mlc1.DrawYaxisLeftGridLines = False                'NEW - ADDED 23 OCT 2015
    mlc1.DrawYaxisRightGridLines = False               'NEW - ADDED 23 OCT 2015
  
'   mlc1.YaxisLeftMinVal = -600                       'AMENDED 22 OCT 2015 TO SET LEFT Y AXIS MIN VAL INDEPENDANTLY - comment it out so that the scale will be set automatically
'    mlc1.YaxisLeftMaxVal = 1600                       'AMENDED 22 OCT 2015 TO SET LEFT Y AXIS MAX VAL INDEPENDANTLY - comment it out so that the scale will be set automatically

'   mlc1.YaxisRightMinVal = -175                      'AMENDED 22 OCT 2015 TO SET RIGHT Y AXIS MIN VAL INDEPENDANTLY - comment it out so that the scale will be set automatically
'    mlc1.YaxisRightMaxVal = 175                       'AMENDED 22 OCT 2015 TO SET RIGHT Y AXIS MAX VAL INDEPENDANTLY - comment it out so that the scale will be set automatically
  
    mlc1.YaxisTextSize = 10.0
  
    mlc1.YaxisLeftTextColor = Colors.Cyan              'NEW - ADDED 23 OCT 2015   
    mlc1.YaxisRightTextColor = Colors.Yellow          'NEW - ADDED 23 OCT 2015
  
    mlc1.ShowYaxisRightLabels = True
    mlc1.ShowYaxisLeftLabels = True
  
    mlc1.DrawLeftGridDashed = False                   'NEW - ADDED 23 OCT 2015
    mlc1.DrawRightGridDashed = True                   'NEW - ADDED 23 OCT 2015
  
    mlc1.YaxisTextAngle = -15                         'NEW - 'ADDED ABILITY TO SET THE ANGLE OF THE Y AXIS LABELS BETWEEN -90 and 90 - 22 OCT 2015
    mlc1.HorizontalGridColorLeft = Colors.Cyan        'NEW - 'ADDED ABILITY TO SET THIS COLOR - 22 OCT 2015
    mlc1.HorizontalGridColorRight = Colors.Yellow     'NEW - 'ADDED ABILITY TO SET THIS COLOR - 22 OCT 2015
  
    mlc1.CubicIntensity = Array As Float(0.1, 0.2, 0.3, 0.4, 0.5)
    mlc1.DrawCubicGraph = Array As Boolean(True, False, True, False, True)
    mlc1.DrawDashedLine = Array As Boolean(True, False, True, False, True)
    mlc1.GraphCircleSize = Array As Float(4.0, 5.0, 6.0, 7.0, 8.0)
    mlc1.GraphCircleColor = Array As Int(Colors.Red, Colors.Green, Colors.Magenta, Colors.Black, Colors.Blue)
    mlc1.DrawGraphHollowCircles = Array As Boolean(True, False, True, False, True)
    mlc1.MarkerToUse = 4
  
    mlc1.XAnimate = False
    mlc1.YAnimate = True
    mlc1.ChartAnimationTime = 2000                     'milliseconds
  
'   the number of charts to be drawn (maximum 5, in this case 5)
'   the number of x-axis values per chart (in this case 12 = number of elements in the array passed to mlc1.XaxisLables)
    mlc1.setLineData(2,12)
    flag = flag + 1
  
  
'    mlc1.saveToGallery("mygraph", 50, mlc1.Width, mlc1.Height)
'     mlc1.saveToPath("mygraph","", mlc1.Width, mlc1.Height)
  
  
  
  

End Sub

Sub Activity_Resume
  
    t.Enabled = True

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub t_tick
  
    mlc1.SavedImageBackgroundColor = Colors.red
    mlc1.saveToGallery("mygraph", 50)
    DoEvents
    mlc1.saveToPath("mygraph","")
    DoEvents
  
    t.Enabled = False
  
    DoEvents
    mlc1.Visible = False
    DoEvents
  
    ImageView1.Left = mlc1.Left
    ImageView1.Top = mlc1.Top
    ImageView1.Height = mlc1.Height
    ImageView1.width = mlc1.width
    ImageView1.Bitmap = mlc1.ChartBitmap
    ImageView1.Visible = True
  
End Sub
 

Attachments

  • b4aMPMultiLineChartV3.zip
    30.4 KB · Views: 322
  • mpChartLib.zip
    323 KB · Views: 335

Mahares

Expert
Licensed User
Longtime User
@Johan Schoeman: Please check the below:
This creates a file on the Sd card which works: mlc1.saveToPath("mygraph","")
But this one does not create the file in a folder on the SD card called BLOB mlc1.saveToPath("mygraph","BLOB")
It might also be better if you do not limit the file creation to the SD card, perhaps change the syntax to something more in line with B4A:
mlc1.saveToPath("mygraph",Dir) where Dir can be File.DirRootExternal, File.DirDefaulttExternal, File.DirInternal, File.DirRootExternal & "/BLOB", etc.
 

Johan Schoeman

Expert
Licensed User
Longtime User
Try /BLOB and not just BLOB...
 

Paulsche

Well-Known Member
Licensed User
Longtime User
ok, works Save as file, but me it would be enough if I would get the graphics as a bitmap. If that does not work, then I'll save the image as a file (preferably in the APP folder) and load them again, would not be so bad.
 

Johan Schoeman

Expert
Licensed User
Longtime User
ok, works Save as file, but me it would be enough if I would get the graphics as a bitmap. If that does not work, then I'll save the image as a file (preferably in the APP folder) and load them again, would not be so bad.
It already returns a bitmap. That is what I am displaying in ImageView1 of the project in the above post.....? It is not loaded from a file. ImageView1 is displaying the returned bitmap. Follow the code....
 

Paulsche

Well-Known Member
Licensed User
Longtime User
It already returns a bitmap. That is what I am displaying in ImageView1 of the project in the above post.....? It is not loaded from a file. ImageView1 is displaying the returned bitmap. Follow the code....

super, thank you, I will test it equal.

Edit: Works fine, thank you
 
Last edited:

Johan Schoeman

Expert
Licensed User
Longtime User
a combinated (multi bar charts and line charts) would be nice !
Here it is. It will draw multiple line charts (I have allowed for 5 line charts) and a single bar chart on the same graph. Posting the new B4A library files and the B4A project demonstrating this. Position of labels, angles of labels, etc, etc are as per previous posted graphs - most notably:
mlc1.setTheLegendPositionAndForm("BELOW_CHART_CENTER","SQUARE") - and its various variants (see previous posts)
mlc1.LineAxisDependency = "RIGHT" - and its various variants (see previous posts)
mlc1.XaxisLabelPosition = "TOP_INSIDE" - and its various variants (see previous posts)
mlc1.BarAxisDependency = "LEFT" - and its various variants (see previous posts)

The "save" and "bitmap return" options have been added to this wrapper too.



Sample Code:

B4X:
#Region  Project Attributes
    #ApplicationLabel: MPMultiLineBarChart
    #VersionCode: 1
    #VersionName:
    'SupportedOrientations possible values: unspecified, landscape or portrait.
    #SupportedOrientations: landscape
    #CanInstallToExternalStorage: False
#End Region

#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: True
#End Region

Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.
 


End Sub

Sub Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.
 
    Private mlc1 As MultiLineBarChart
 
End Sub

Sub Activity_Create(FirstTime As Boolean)
    'Do not forget to load the layout file created with the visual designer. For example:
    Activity.LoadLayout("main")
 
'*********************************** GENERAL CHART SETUP STARTS HERE
 
    mlc1.GridBackgroundColor = Colors.Transparent
 
    mlc1.DrawBorders = True
    mlc1.BorderColor = Colors.Red
    mlc1.BorderWidth = 3 
 
    mlc1.LegendShapeSize = 10.0
    mlc1.setTheLegendPositionAndForm("BELOW_CHART_CENTER","SQUARE")
    mlc1.TheLegendTextColor = Colors.Yellow
    mlc1.TheLegendTextSize = 10.0 
    mlc1.LegendEntrySpace = 50.0 

    mlc1.ChartDescription = "MULTI LINE AND SINGLE BAR CHART"
    mlc1.ChartDescriptionTextSize = 30.0
    mlc1.ChartDescriptionColor = Colors.red
    mlc1.setDescriptionPosition(mlc1.Left + (mlc1.Width/2), mlc1.Top + 10%y)
 
    mlc1.MarkerToUse = 4
    mlc1.DrawMarkerViews = True
 
    mlc1.PinchZoom = True 
 
'******************************************* LINE CHART SET UP STARTS HERE
 
    mlc1.NumberOfLineCharts = 5        'change this value from 1 to 5 to draw the 1st, 1st and 2nd, 1st and 2nd and 3rd, etc line charts
 
    mlc1.LineLegendText = Array As String("A", "B", "C", "D", "E")

    mlc1.LineColor = Array As Int(Colors.Green, Colors.Blue, Colors.Magenta, Colors.Cyan, Colors.Yellow)
    mlc1.LineAxisDependency = "RIGHT"
 
    mlc1.Line_1_Data = Array As Float(56.2, 78.3, 22.4, 55.4, 69.4, 103.8, 45.7, 36.4, 62.4, 44.6, 36.4, 70.5)
    mlc1.Line_2_Data = Array As Float(36.4, 110.5, 56.2, 78.3, 22.4, 55.4, 69.4, 103.8, 45.7, 36.4, 62.4, 44.6) 
    mlc1.Line_3_Data = Array As Float(62.4, 44.6, 36.4, 110.5, 56.2, 78.3, 22.4, 55.4, 69.4, 103.8, 45.7, 36.4) 
    mlc1.Line_4_Data = Array As Float(45.7, 36.4, 62.4, 44.6, 36.4, 110.5, 56.2, 78.3, 22.4, 55.4, 69.4, 103.8) 
    mlc1.Line_5_Data = Array As Float(69.4, 103.8, 45.7, 36.4, 62.4, 44.6, 36.4, 120.5, 56.2, 78.3, 22.4, 55.4) 
 
    mlc1.DrawLineValues = Array As Boolean(True, True, True, True, True)
    mlc1.LineValueTextColor = Array As Int(Colors.Green, Colors.Blue, Colors.Magenta, Colors.Cyan, Colors.Yellow)
    mlc1.LineValueTextSize = 15.0
    mlc1.CubicIntensity = Array As Float(0.2, 0.2, 0.2, 0.2, 0.2)
    mlc1.DrawCubicGraph = Array As Boolean(True, True, True, True, True)
    mlc1.DrawGraphHollowCircles = Array As Boolean(True, True, True, True, True)
    mlc1.GraphCircleColor = Array As Int(Colors.Yellow, Colors.Green, Colors.Blue, Colors.Magenta, Colors.Cyan)
    mlc1.GraphCircleSize = Array As Float(4.0, 5.0, 6.0, 5.0, 4.0)
    mlc1.GraphLineWidth = Array As Float(3.5, 4.0, 4.5, 5.0, 5.5)
    mlc1.DrawDashedLine = Array As Boolean(True, False, True, False, True)

'******************************************** X, Y LEFT, Y RIGHT AXIS SETUP STARTS HERE
    mlc1.RightYaxisTextColor = Colors.Green
    mlc1.RightYaxisTextSize = 15.0
    mlc1.ShowYaxisRightLabels = True
    mlc1.DrawYaxisRightGridLines = True
    mlc1.DrawRightGridDashed = True
 
    mlc1.LeftYaxisTextColor = Colors.Yellow
    mlc1.LeftYaxisTextSize = 25.0 
    mlc1.ShowYaxisLeftLabels = True
    mlc1.DrawYaxisLeftGridLines = True
    mlc1.DrawLeftGridDashed = False     
 
    mlc1.HorizontalGridColorLeft = Colors.Yellow
    mlc1.HorizontalGridColorRight = Colors.Green

    mlc1.XaxisLables = Array As String("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec")
    mlc1.XaxisTextColor = Colors.Cyan
    mlc1.XaxisTextSize = 15.0
    mlc1.XaxisTextAngle = 15
    mlc1.XaxisLabelPosition = "TOP_INSIDE"
    mlc1.DrawXaxisGridLines = True
    mlc1.VerticalGridColor = Colors.Magenta
 
'********************************************** BAR CHART SETUP STARTS HERE 
 
    mlc1.DrawBarChart = True     
    mlc1.BarAxisDependency = "LEFT"
    mlc1.Bar_Data = Array As Float(65.2, 15.3, 22.4, 55.4, 75.4, 38.8, 54.7, 63.4, 26.4, 44.6, 63.4, 60.5)
    mlc1.BarColor = Colors.DarkGray
    mlc1.BarLegendText = "F"
    mlc1.BarValueTextSize = 20.0
    mlc1.BarValueTextColor = Colors.White
    mlc1.DrawBarValues = True
 
'******************************************** SET CHART ANIMATION 
 
    mlc1.XAnimate = False
    mlc1.YAnimate = False
    mlc1.XYAnimate = True
    mlc1.ChartAnimationTime = 1500
 
'******************************************** DRAW THE CHARTS ONCE ALL SETUP HAVE BEEN COMPLETED 
 
    mlc1.DrawCharts
 
'******************************************* ADD YOUR CODE FROM HERE ONWARDS TO SAVE THE GRAPH OR TO RETURN THE BITMAP.
'                                            REMEMBER TO ADD A TIME DELAY BEFORE ATTEMPTING TO SAVE OR BEFORE RETURNING
'                                            THE BITMAP IF ANY OF THE 3 POSSIBLE CHART ANIMATIONS HAS BEEN SET TO TRUE (SEE CODE ABOVE) 

End Sub

Sub Activity_Resume
 


End Sub

Sub Activity_Pause (UserClosed As Boolean)
 


End Sub
 

Attachments

  • b4aMPMultiLineBarChart.zip
    29.4 KB · Views: 319
  • mpChartLib.zip
    332.8 KB · Views: 321
Last edited:

Paulsche

Well-Known Member
Licensed User
Longtime User
Hi Johan, thank you for the effort
 

Paulsche

Well-Known Member
Licensed User
Longtime User
it is also possible Multibarchart + single LineChart ?
 

Johan Schoeman

Expert
Licensed User
Longtime User
it is also possible Multibarchart + single LineChart ?
The original Github project does not support this at present and the work-around for the multi line chart with a single bar chart does not work in the reverse order. Will add it to the library once the Github project supports this option.
 

Paulsche

Well-Known Member
Licensed User
Longtime User
The original Github project does not support this at present and the work-around for the multi line chart with a single bar chart does not work in the reverse order. Will add it to the library once the Github project supports this option.

Thanks
 

Mikonios

Active Member
Licensed User
Longtime User
Thank you very much for sharing this library. It's really good & simple Johan. I fail to fully understand how it works so I ask your help with the following: I need to represent 40 values with 3 decimal float ::: 20151101-1.064;20151102-1.064;20151103-1.064;20151104-1.069;20151105-1.069;20151106-1.069;20151107-1.069;20151108-1.069;20151109-1.069;20151110-1.069;20151111-1.069;20151112-1.076;20151113-1.076;20151114-1.076;20151115-1.076;20151116-1.076;20151117-1.076;20151118-1.069;20151119-1.069;20151120-1.059;20151121-1.049;20151122-1.049;20151123-1.049;20151124-1.049;20151125-1.039;20151126-1.039;20151127-1.029;20151128-1.029;20151129-1.029;20151130-1.029;20151201-1.029;20151202-1.029;20151204-1.029;20151205-1.029;20151206-1.029;20151207-1.029;20151208-1.029;20151209-1.029;20151210-1.029;20151211-1.009;20151212-1.009;20151213-1.009;20151214-1.009;20151215-1.009;

mlc1.YaxisLeftMinVal = 1.0 'No runs. Always start from 0
mlc1.YaxisLeftMaxVal = 1.5

mlc1.MarkerToUse = 2 'Does not display 3 decimal

Both left and right shows a dedimal of more.
Thanks in advance Johan




 

Johan Schoeman

Expert
Licensed User
Longtime User
Please zip your project and upload it so that I can take a look at it. There are various options to draw line charts with and I don't know which one you are using.
 

Mikonios

Active Member
Licensed User
Longtime User
I fear that the library does not respect the changes:

mlc1.setTheLegendPositionAndForm ("BELOW_CHART_CENTER", "circle")
mlc1.XaxisLabelPosition = "BOTTOM"

in the example draw_graph_7 if any value is changed as the color does not maintain the parameters.
Sorry the problem occurs in rapid debug mode. In mode Release work fine!!
 
Cookies are required to use this site. You must accept them to continue using the site. Learn more…