EKON 29 Statistic Packages Slides

Statistic Packages Overview 2025

https://github.com/maxkleiner/maXbox5/tree/main/EKON29

  • Regression & Correlation box script demos
  • 7 Statistic Methods & 5 Diagramtypes
  • Stats Package TeeChart & mrMath, Delphi AI
  • Sklearn & Statsmodels (P4D)
  • AGSI, JSON, EdgeView2 and Weather Reports
  • Alternate Packages, Top & Flops Statistic
  • This session shows various ways of using statistic and plots in your apps.

📊

ML Magazine – Visualization of Machine Learning Data

https://devm.io/reader/reading/ml-magazine/Volume%204/8533ef95484202124e17eaf9?fromSearch=true

A Base Class

System.Math.MomentSkewKurtosis is declared as

procedure MomentSkewKurtosis(const Data: array of Double; var M1,M2,M3,M4,Skew,Kurtosis,Extended);

Ex.: MomentSkewKurtosis ([1,2,3,4,5,5,5,6,7,8,9] ,M1,M2,M3,M4,Skew,Kurtosis)
writ(format('%2f %2f %2f %2f %2f %2f',[M1, M2, M3, M4, Skew, Kurtosis]))
5.00 5.45 0.00 64.36 0.00 2.16

MomentSkewKurtosis: Calculates the core factors of statistical analysis: the first four moments plus the coefficients of skewness and kurtosis.

  • M1 is the Mean.
  • M2 is the Variance.
  • Skew reflects symmetry of distribution: M3 / (M2**(3/2))
  • Kurtosis reflects flatness of distribution: M4 / Sqr(M2)
  • Look at M3 and M4 (the 3rd and 4th order moment) as helper variables in order to calculate skew and kurtosis (extracted from source):

https://github.com/fundamentalslib/fundamentals5/blob/master/Source/Maths/flcStatistics.pas

https://github.com/project-jedi/jcl/blob/master/jcl/source/common/JclStatistics.pas

https://github.com/TurboPack/SysTools/tree/master/source

https://github.com/TurboPack/SysTools/blob/master/source/StStat.pas

https://github.com/fundamentalslib/fundamentals5/blob/master/Source/Maths/flcStatistics.pas

Fundamentals 5 Library

Fundamentals 5 Code Library for Delphi and FreePascal

Includes:

  • String, DateTime and dynamic array routines
  • Unicode routines
  • Hash (e.g. SHA256, SHA512, SHA1, SHA256, MD5)
  • Integer (e.g. Word128, Word256, Int128, Int256)
  • Huge Word, Huge Integer
  • Decimal (Decimal32, Decimal64, Decimal128, HugeDecimal and signed decimals)
  • Random number generators
  • Cryptographic (Symmetric: AES, DES, RC2, RC4; Asymmetric: RSA, Diffie-Hellman, Elliptic Curve)
  • Data structures (array, dictionary and map classes)
  • Mathematics (Rational number, complex number, vector, matrix, statistics)
Correlation Matrix Code

A Brain Class

Brain Train

https://github.com/maxkleiner/maXbox5/blob/main/EKON29/1442_Statistics_unittest.pas

7 Statistical Methods Criteria

  • 1. Bayesian Inference (p(A))
  • 2. Hypothesis Testing (t-test)
  • 3. Factor Analysis (Loading Analysis)
  • 4. Cluster Analysis (K-means)
  • 5. Logistic Regression Classifier
  • 6. Monte Carlo Simulation (Rnd)
  • 7. Time Series Analysis (ARIMA)
  • Data science is a multidisciplinary field that combines math, statistics, computer science, machine learning, and domain expertise to extract insights from data. While data science algorithms often put the spotlight, a solid foundation in statistical methods can be just as pivotal.

5 Important Diagram Types

Here, I’ll show you how to analyze a runtime script created dataset and extract meaningful insights with 5 diagram types:

  • Bar Chart
  • Scatter Plot
  • Histogram
  • Box Plot
  • Correlation Matrix

Stats Dependencies

Systools Stats, JEDI and P4D

Cross-platform class TChart

  • TeeChart is a powerful charting component developed by Steema Software, widely used in Delphi and C++Builder environments. It provides a comprehensive set of tools for creating various types of charts, including line, bar, area, pie, point, and horizontal bar charts, which can be viewed in both 2D and 3D formats.
  • Key Features
  • Versatility: TeeChart supports a wide range of chart types and can be used for business, real-time, financial, and scientific applications. It is included in most Delphi and C++Builder products and supports both VCL and FM.
  • Cross-Platform Support: TeeChart can be used to create applications for Windows (x32/x64) and macOS. For Apple iOS support, TeeChart Pro.
  • Interactivity: TeeChart allows users to interact with charts by zooming, panning, and exporting to various file types. This makes it suitable for applications that require real-time data visualization and user interaction.

Demo: 820_U_ProbabilityDist2ekon29_1_64.pas

GUI or Console?

Lottery and Population

Mr Math Package

https://github.com/mikerabat/mrmath/blob/master/Statistics.pas

Demo: TestdemoStatisticClassifier64bit.exe

Important: On top of these classifiers there exists a few image database handling routines

and an 1D, 2D Haar Feature extractor which is based on an integral image approach.

The mrMath, mrStats, mrMatrix, mrImgUtils package includes:

  • Standard Fisher LDA classifier
  • Robust (and Fast Robust) version of this classifier
  • Incremental (and Robust) Fisher LDA classifier learning.
  • Support Vector Machines (least squares and lagrangian learning)
  • Naive Bayes
  • Simple Decission stumps
  • Radial basis function
  • C4.5 Decission trees.
  • K-means
  • Ensemble classifiers: AdaBoost, Gentle Boost, Bagging
  • Simple feed forward Neural Nets

Mr Math II Test

Stat Control

Code Control II

Write a stateful function, class, generator or co-routine that takes a series of floating point numbers, one at a time, and returns the running standard deviation of the series.

Use this to compute the standard deviation of this demonstration set, {2,4,4,4,5,5,7,9} which is 2. {\displaystyle \{2,4,4,4,5,5,7,9\}}

Gas storage timeline AGSI dataset

https://wiki.freepascal.org/pas2js_Electron_Web_Application

The data science tutorial explains the so called AGSI data storage and his visualization of the timeline. AGSI is the Aggregated Gas Storage Inventory and offers you the possibility to be kept up to date whenever a new service announcement or update from one of our data providers is posted on the website.

Statsmodels

Statsmodels is a Python library designed for statistical modeling, hypothesis testing, and data exploration with high reference.

It provides a wide range of statistical models, including linear regression, time series analysis, and generalized linear models.

The library supports both formula-based modeling (similar to R) and direct use of NumPy arrays.

Demo: 1417_statsmodels_64_delphi_python3.12.4debug130_EKON29.txt

Second multivariate with a higher R2:

 Execstr(‘model=smf.ols(“Lottery~ Wealth+Literacy+np.log(Pop1831)+Suicides+Donations”,data=df).fit()’);

R2 of 0.492
                            OLS Regression Results                            
==============================================================================
Dep. Variable: Lottery R-squared: 0.492
Model: OLS Adj. R-squared: 0.461
Method: Least Squares F-statistic: 15.51
Date: Thu, 02 Oct 2025 Prob (F-statistic): 1.20e-10
Time: 17:54:49 Log-Likelihood: -369.10
No. Observations: 86 AIC: 750.2
Df Residuals: 80 BIC: 764.9
Df Model: 5
Covariance Type: nonrobust
===============================================================================
coef std err t P>|t| [0.025 0.975]
-------------------------------------------------------------------------------
Intercept 180.2691 35.830 5.031 0.000 108.965 251.573
Wealth 0.1715 0.094 1.833 0.070 -0.015 0.358
Literacy -0.2409 0.126 -1.911 0.060 -0.492 0.010
np.log(Pop1831) -25.1121 5.699 -4.407 0.000 -36.453 -13.771
Suicides 0.0002 7.37e-05 3.323 0.001 9.82e-05 0.000
Donations 0.0005 0.000 1.490 0.140 -0.000 0.001
==============================================================================
Omnibus: 6.163 Durbin-Watson: 1.665
Prob(Omnibus): 0.046 Jarque-Bera (JB): 5.537
Skew: -0.594 Prob(JB): 0.0628
Kurtosis: 3.363 Cond. No. 8.85e+05
==============================================================================

Notes:
[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.
[2] The condition number is large, 8.85e+05. This might indicate that there are
strong multicollinearity or other numerical problems.
('version:', '3.13.3 (tags/v3.13.3:6280bb5, Apr 8 2025, 14:47:33) [MSC v.1943 64 bit (AMD64)]')
dept Region Department Crime_pers Crime_prop Literacy Donations Infants Suicides MainCity Wealth Commerce Clergy Crime_parents Infanticide Donation_clergy Lottery Desertion Instruction Prostitutes Distance Area Pop1831

Statsmodels Code

  • We download the Guerry dataset, a collection of historical data used in support of Andre-Michel Guerry’s 1833 Essay on the Moral Statistics of France. The data set is hosted
  • online in comma-separated values format (CSV) by the Rdatasets repository. We could download the file locally and then load it using read_csv, but pandas takes care of all of this automatically for us:

Execstr(‘model = smf.ols(“Lottery ~ Wealth + Literacy + np.log(Pop1831)”, data=df).fit()’);

Code Behind Dataframe

P4D Primer

EdgeView2 SDK for Stats

  • McJson use a Simple Object-Pascal native code using TList as internal data structure with a Single-pass string parser and is just one unit (McJSON) and just one class(TMcJsonItem) integrated in maXbox or Lazarus.
  • RAD Studio 10.4 Sydney brings support for working with web content through the Chromium-based Edge WebView2 browser control in VCL applications via the new TEdgeBrowser component.
  • Demo: 1324_weatherbox_regex_64_maincities.txt

https://sourceforge.net/projects/maxbox5/files/binaries/WebView2Loader_2739.dll/download

JS-Pas-Solution

  • These projects have been selected based on their popularity, technical significance, and impact on the Delphi development community. They represent a mix of developer tools, frameworks, and components.
  • Integrate dynamic, interactive, custom maps, statistic data and geospatial data into your apps by embedding JS:
  • Weather, Navigation or Trafic Data uses huge statistical data with representation

1312_API_Demo64_5_javascript_maps.txt

Other Packages

Several statistical packages and libraries are available for Delphi, ranging from commercial solutions to open-source and freeware options.

These packages support a wide range of statistical computations, from basic descriptive statistics to advanced multivariate analysis.

Tops & Flops Stats (from API to AI)

  • **1. Awesome Delphi***
  • **2. Delphi IDE Theme Editor**
  • **3. DelphiMVCFramework (DMVCFramework)**
  • **4. Delphi REST Client API***
  • **5. Virtual-TreeView**
  • **6. Delphi-OpenCV***
  • **7. DUnitX**
  • **8. Delphi IDE Colorizer**
  • **9. CEF4Delphi***
  • **10. OmniThreadLibrary**

https://github.com/maxkleiner/maXbox/blob/master/objectdetector3.ipynb

These projects have been selected based on their popularity, technical significance, and impact on the Delphi development community. They represent a mix of developer tools, frameworks, and components (perplexity,chatgpt,gemini prompts).

Tops & Flops Explain

https://github.com/maxkleiner/maXbox/blob/master/objectdetector3.ipynb

**1. Virtual-TreeView**

A highly flexible and powerful tree view control, Virtual-TreeView has become a staple in both open-source and commercial Delphi applications.

Its performance and extensibility have set the standard for advanced UI components in Delphi, making it one of the most influential libraries

in the ecosystem[1].

**2. OmniThreadLibrary**

This threading library greatly simplified the development of multi-threaded applications in Delphi. Its ease of use and robust feature

set have made it the go-to solution for Delphi developers needing parallelism and concurrency, ensuring Delphi apps remain competitive

on modern multi-core hardware[1].

**3. DelphiMVCFramework (DMVCFramework)**

As web development became critical, DMVCFramework provided Delphi developers with a modern, powerful framework for building

RESTful web applications and APIs. Its adoption has helped keep Delphi relevant in server-side and web API development[1].

**4. CEF4Delphi**

By enabling the embedding of Chromium-based browsers in Delphi applications, CEF4Delphi has allowed developers to

integrate modern web technologies and content directly into native apps, bridging the gap between desktop and web[1].

**5. DUnitX**

Unit testing is essential for modern software development, and DUnitX brought advanced, NUnit-inspired testing

capabilities to Delphi. Its adoption has fostered better software quality and test-driven development practices in the Delphi community[1].

**6. Delphi-OpenCV**

This project brought the power of the OpenCV computer vision library to Delphi developers, opening up new

possibilities in image processing and AI within the Delphi ecosystem[1].

**7. Delphi REST Client API**

As RESTful APIs became the backbone of modern applications, this library enabled Delphi developers to

easily consume web services, ensuring Delphi’s continued viability for connected applications[1].

**8. Awesome Delphi**

While not a library or component, this curated list of high-quality Delphi resources has become an essential

starting point for developers, helping to foster community and knowledge sharing[1].

**9. Delphi IDE Theme Editor & Delphi IDE Colorizer**

These tools have modernized the developer experience, allowing for extensive customization

and theming of the Delphi IDE, which has contributed to the productivity and satisfaction of Delphi programmers[1].

Flops

  • **1. Delphi 8 and Delphi 2005 Releases**
  • **2. Dreaded Sorts (THSorts) Demo**
  • **3. Component Colossus Projects**
  • **4. Projects Stuck on Old Delphi Versions**
  • **5. Projects Dependent on Discontinued Technologies**
  • **6. DLL Hell Projects**
  • **7. Over-Componentized “Flavor of the Month” Projects**
  • **8. Projects Broken by Unicode Transition**
  • **9. Projects with Inflexible Architectures**
  • **10. “Reinventing the Wheel” Projects**

Conclusion

  • https://softwareschule.code.blog/2025/02/20/7-data-science-statistical-methods/
  • Config and spec features of DMath, SKLearn, Statsmodels, mrMath library
  • Troubleshooting: Typical miscalculations and their solutions with cleaned data
  • Typical Features of these Packages
  • Descriptive stats: mean, median, mode, variance, percentiles
  • Probability distributions (PDF, CDF, inverse CDF)
  • Random number generation
  • Hypothesis testing (t-tests, chi-squared, ANOVA)
  • Regression (linear, logistic, ridge, Poisson, non-linear)
  • Multivariate techniques (PCA, factor analysis)
  • Data visualization, function approximation
  • Check the statistic package like TEE in feature-matrix
  • https://www.embarcadero.com/docs/rad-studio-feature-matrix.pdf

https://raw.githack.com/breitsch2/maXbox4/master/assets/graph3.html

Method: Correlation

Plot: List or Matrix

View: Form or Browser

Many Thanks for coming!

Many Thanks for coming!

Materials:

http://www.softwareschule.ch/download/maxbox_starter140.pdf

http://www.softwareschule.ch/download/maxbox_starter149.pdf

https://blogs.embarcadero.com/why-a-data-scientist-chooses-delphi-for-powerful-real-world-visualizations/

Dienstag, 28. Oktober 2025

11:45 – 12:45, Max Kleiner

https://sourceforge.net/projects/maxbox5/files/EKON29/

Origin Slides:

Click to access maxbox_starter157.pdf

https://de.scribd.com/document/925708175/Maxbox-Starter157-EKON29-Statistic-Packages-2sign

Jouef est une marque d’origine française de modèles réduits de trains et de circuits routiers, créée en 1944 par Georges Huard à Champagnole, dans le département du Jura.

TEE Aquitaine
Roco CC 6514 et Jouef CC 6515
Jouef Collection CC 21001- 21004 SNCF

Delphi Quiz 30 Jahre Delphi EKON 29

A must see Operation System history
https://lnkd.in/e_KjeJdd

—————————-

1. Ab welcher Delphi Version is der String ein Unicodestring?

Antwort: Ab Delphi 2009 ist string ein UnicodeString und speichert Zeichen in UTF-16-Kodierung.

2. Welche Koierung wird in Unicode gebraucht?

UTF-16 BE oder UTF-16 LE
Antwort: UTF-16 LE (Little Endian)

3. Wie hiess der Codename von Delphi 2006?

A: DeXter

4. Wie hiess der Codename von Delphi XE6?

A: Tiburón

5. Wann ist der Vater von Pascal gestorben?

A: Januar 2024

6. Was ist der grösste Datentyp in Delphi?

A: Größter dynamischer Typ: string (UnicodeString, bis zu 2 GB möglich).

7. Von wem stammt das Buch Delphi 7 Kochbuch?

A: Von Walter Doberenz, Thomas Kowalski:

8. Seit wann gibt es Closures in Delphi?

A: Closures wurden in Delphi mit der Einführung von anonymen Methoden ab Delphi 2009 

(Version 12, auch bekannt als Delphi Prism) unterstützt.

9. Was bedeutet ARC in Delphi?

A: automatische Referenzzählung (ARC) as automatic reference counter.

10. Wo in Delphi wird Nil definiert?

A: In Delphi wird nil als Konstante in der System-Unit definiert und hat den Wert von Pointer(0).

Stochastic Pic IV
Taiheikaku-Bridge, Made in Japan – Saint & Print – 平安神宫 Heian Jingu Shrine

Finds a non-euclidean distance or similarity between two strings.

Jaro and Jaro-Winkler equations provides a score between two short strings where errors are more prone at the end of the string. Jaro’s equation measure is the weighted sum of the percentage of matching and transposed characters from each string. Winkler’s factor adds weight in Jaro’s formula to increase the calculated measure when there is a sequence of characters (a prefix) in both strings.

  writeln(formatfloat('0.######', ssJaroWinkler('DWAYNE', 'DUANE')));
  writeln(formatfloat('0.######', ssJaroWinkler('MARTHA', 'MARHTA')));
  writeln(formatfloat('0.######', ssJaroWinkler('DIXON', 'DICKSONX')));
  writeln(formatfloat('0.######', ssJaroWinkler('JELLYFISH', 'SMELLYFISH')));

The complexity of this algoritme resides in finding the matching and transposed characters. That is because of the interpretation of what are the matching conditions and the definition of transposed. Definitions of those two will make the score vary between implementations of this algorithme.

Install Py3.15 instead of Py3.14 (P4D Support Helpdesk)

The Standard install scanner in PythonEngine.pas checks KOWN_VERSIONS till 3.14 so how do you test Python4Delphi with a new 3.15?

  (DllName: 'python312.dll'; RegVersion: '3.12'; APIVersion: 1013),
    (DllName: 'python313.dll'; RegVersion: '3.13'; APIVersion: 1013),
    (DllName: 'python314.dll'; RegVersion: '3.14'; APIVersion: 1013)
    ); 
 (DllName: 'libpython3.12.so'; RegVersion: '3.12'; APIVersion: 1013),
    (DllName: 'libpython3.13.so'; RegVersion: '3.13'; APIVersion: 1013),
    (DllName: 'libpython3.14.so'; RegVersion: '3.14'; APIVersion: 1013)

https://github.com/pyscripter/python4delphi/blob/master/Source/PythonEngine.pas

First you install the normal way your Py Windows Installer:

After the you rename the Default PATH from “C:\Users\User\AppData\Local\Programs\Python\Python315” to “C:\Users\User\AppData\Local\Programs\Python\Python314” and rename also the python315.dll to python314.dll. Note: your old active C:\Users\User\AppData\Local\Programs\Python\Python314 has to be set before to C:\Users\User\AppData\Local\Programs\Python\Python314_ as a save backup.

Rename the active path to Python314_ and then rename Python315 to Python 314 (include DLL python314.dll )!

Then you should see with ExecString(‘import sys,io,time’); and sys.version:

pyout: (3, '3.15.0a1 (tags/v3.15.0a1:aeff92d, Oct 14 2025, 11:51:55) [MSC v.1944 64 bit (AMD64)]')
pyout: (4, '3.15.0a1 (tags/v3.15.0a1:aeff92d, Oct 14 2025, 11:51:55) [MSC v.1944 64 bit (AMD64)]')
PythonOK True cl.count:2

Scripted Runtime Version of P4D:

https://github.com/maxkleiner/python4delphi/blob/master/Source/uPSI_PythonEngine.pas

Caution: After rename the path you could not use pip to install more packages:

path from 3.15 is now 3.14
C:\maxbox\maxbox51>py -3.14 -m pip install pandas
C:\maxbox\maxbox51>py -3.14 -m pip install scikit-learn
C:\maxbox\maxbox51>py -3.14 -m pip install matplotlib
C:\maxbox\maxbox5\pascriptmaster2\pmaster2\restunits\Indy9\maxbox5\maxbox5>py -3.14 -m pip install statsmodels
https://sourceforge.net/projects/maxbox5/files/examples/1442_RandomGenMersenne_mX52.pas/download
https://entwickler-konferenz.de/delphi-innovations-fundamentals/statistic-packages-fuer-delphi-oder-python/
https://github.com/maxkleiner/maXbox5/tree/main/EKON29

Weather Stat Forecast Package

In this example we examine Solingen/DE

Train Station main station

Notes concerning Stat Pacs Overview

TeeChart

TeeChart in Delphi offers a wide range of statistical functions that can be used for data presentation and analysis.

The Pro version of TeeChart includes approximately 56 mathematical, statistical, and financial-oriented functions, while the standard version also supports numerous basic statistical functions.

  • Overview of Statistical Functions in TeeChart
    Descriptive Statistics: Mean, Median, Minimum, Maximum, Standard Deviation, Variance.
  • Regression Functions: Linear, Exponential, and Polynomial Regression.
  • Distribution Functions and Normal Distribution (Gaussian Distribution).
  • Moving Average.
  • Historograms and Boxplots for graphically displaying distributions and outliers.
  • Correlation Analysis and Trend Lines.

Special statistical charts such as: Normal Probability Plot, Weibull Probability Plot, Quantile-Quantile Plot, quality control charts (e.g., XBar, R, S, P, NP, U, C), EWMA, and Levey-Jennings Chart.

Many of these statistical functions are available as so-called “functions” (e.g., TMeanFunction, TrendFunction, TMovingAverageFunction) and can be applied directly to chart series.

Advanced Analyses Process Capability Statistics (Cp, Cpk, p), often for quality control. Dot plots and biplots for multivariate data analysis. With these functions and visualizations, you can perform statistical analyses in Delphi with TeeChart and display the results graphically.

JCL Statistics

The statistical functions in the Delphi component library JCLStatistics (part of the JEDI Code Library) often referred to as JCL) cover the most important standard functions of descriptive and inferential statistics for basic data analysis and evaluation.
The JCLStatistics unit offers, in particular:

  • Overview of Typical Functions in JCLStatistics
    Calculation of mean, median, minimum, and maximum.
  • Sum, product, variance, and standard deviation.
  • Skewness and kurtosis.
  • Special functions such as mode (most frequent value).
  • Quantiles and percentiles.
  • Range and range.
  • Various summary evaluations.

The functions are typically available as individual procedures and functions such as mean, median, variance, etc. (often in the JclStatistics.pas unit). They are designed more for classic descriptive analyses,
but advanced statistical models such as regression or complex trend analyses are not included in JCLStatistics. Other libraries such as TeeChart or third-party components are better suited for such tasks.

Systools

Available as Getit package
The SysTools library for Delphi provides a collection of utility routines and classes, which also includes useful mathematical and some basic statistical functions. However, its focus is primarily on practical helpers, not on advanced statistical models.

  • Statistical Functions in SysTools
    Basic arithmetic operations: sum, mean, minimum, maximum, etc.
  • Sorting functions and high-precision mathematics.
  • 1-D & 2-D barcode creation and money routines.
  • Runtime math expression analyzer.
  • Other math helpers such as standard deviation, random number generator, rounding functions, and logarithmic operations.
  • No complex statistical models such as regression, correlation analysis, or distribution functions are included by default.

SysTools is suitable for numerical analyses and mathematical utility functions. For advanced statistical methods, Delphi libraries such as TeeChart, DMath, or scientific statistical packages (e.g., SDL Component Suite) are a more sensible choice.

Fundamentals 5
The statistical functions in Fundamentals 5, especially in the flcStatistics unit for Delphi,
cover the most important numerical and statistical analyses. Fundamentals 5 is a modern, open-source code base that provides many mathematical and data-related methods, including statistics.

  • Key Statistical Functions in flcStatistics (Fundamentals 5)
    Mean, median, minimum, maximum.
  • Variance, standard deviation.
  • Sum, product, and various aggregate functions.
  • Quantiles, percentiles, and range calculations.
  • Skewness, kurtosis.
  • Mode (most frequent value) and sorting of data series.
  • Basic random number generators.
  • For vectors and matrices: sum, product, norms, statistical measures of dispersion.

These functions are applicable to numeric arrays and generic data types and are based on classic statistics APIs. Fundamentals5 differs in its modern, universal, and packaged architecture, offering many mathematical and statistical methods from a single library.

TMS Physics Pack

Yes, TMS Software offers a “TMS Analytics & Physics Pack,” which is offered as a statistics and analysis package for Delphi.

Conclusion

The best statistics package for Delphi depends largely on the specific application, the required range of functions, and whether you value graphical visualization or robust numerical analysis. However, the following packages have proven particularly effective in the professional and enterprise sectors:

Recommendations for leading statistics packages in Delphi
TeeChart: Comprehensive, commercial toolkit for data visualization with 50+ statistical functions, supports many complex analyses, and offers very powerful graphical output. Also regressions, trends, histograms, box plots, and much more.

TMS Analytics & Physics Pack: Specifically for numerical and analytical statistics, including symbolic calculations, approximation, data fitting, numerical integration, and matrix calculations. Ideal when analytical methods and data science aspects are paramount.

JCLStatistics (JEDI): Open source, suitable for basic analysis, fast and easy to use, but less complex procedures. Suitable for standard statistics in code, but not for graphical analysis.

Fundamentals5 (flcstatistics): A very modern, object-oriented open-source solution with a wide range of numerical methods, particularly suitable for developers who value generic and portable statistical functions.

SDL Component Suite: Commercial, very broad mathematical and statistical spectrum, also recommended for specialized areas such as signal processing, medicine, or chemistry.

https://www.lohninger.eu/sdlindex.html

  • Key Selection Criteria
    For comprehensive graphical and numerical statistics: TeeChart or TMS Analytics & Physics Pack.
  • For open, easy integration of pure statistical data: JCL Statistics or Fundamentals5.
  • For specialized scientific and industrial applications: SDL Component Suite.

There is no “absolutely best” statistical package – the choice depends on project requirements, budget, and the need for visual or analytical depth. In many enterprise applications, TeeChart is the leader, while in scientific applications, SDL Suite is often the choice, and in open-source projects, JCL or Fundamentals5 are often the choice.

http://datalab.epina.at/en_home.html

Epina DataLab is a simple to use statistics package running under Windows offering a well-balanced mixture of data editing capabilities, visualization methods and mathematical and statistical procedures. DataLab has been developed as a small but powerful tool for data manipulation and interpretation. The methods implemented in this package have been selected from a practitioners view.

DataLab

Train Rain

This is the first iteration of the altair visualization of the scatterplot we made. Already the primary difference from the sketches is that the x and y axis have changed, with the y now showing the liquor licenses per 10k people and the x showing the percentage of binge drinkers in that city’s county, with each dot representing a city. 

Heat maps showing the amount of drunk driving crashes in Denver and Boulder county
from 2003 to 2025 I was 50 times at Cologne!
4 Nation Locs Minitrix 103 237-4, My 1103, Arnold CC 21001, Kato Re 6/6 11630
TEE Mediolanum by KATO
from EKON 1 to EKON 29 https://de.slideshare.net/maxkleiner1

Master Python Course

https://dev.to/onlineproxy/a-pragmatists-guide-to-mastering-pythons-foundations-4p8j

This guide to AI data visualization breaks down the essentials of understanding and improving complex datasets with examples, tools, and proven strategies to support better model development and decision-making.

When it comes to AI, large and complex datasets are a necessary evil. To build accurate and reliable AI models, it is important to truly understand the data being used. 

EKON 29

Statistic Packages for Delphi and Python

A truly cross-platform library for numerical analysis and statistical functions isn’t easy to find in Delphi. Especially since quality and licensing are also important. In this session, we’ll delve into the most useful packages and libraries suitable for performing statistical calculations, all the way up to advanced modeling and data visualization. We’ll also compile a statistics on the top and flops of Delphi projects over the past 30 years.

https://entwickler-konferenz.de/delphi-innovations-fundamentals/statistic-packages-fuer-delphi-oder-python

Hands-On

  • Setting up the mrMath and mrMatrix mrAI toolchain
  • Open AI for Delphi Demo
  • Calculating DMath correlations, pattern recognition, and trends
  • Introducing the 7 well-known statistical methods
  • Demonstrating the 5 most important chart types (Bar Chart, Scatter Plot,
    Histogram, Box Plot and Correlationmatrix)
  • Setting up an energy storage time series AGSI project statistics
  • Descriptive statistics with the reference dataset for morale statistics (Guerry, “HistData”)
  • Data Science Tutorial AGSI or Guerry

Contents

  • Overview of the statistical packages with Delphi and Python (P4D).
  • Configuration and spec features of DMath, SKLearn, Statsmodels, & DataLab library
  • Troubleshooting: Typical miscalculations and their solutions with cleaned data
  • First steps in implementing regression, cluster analysis, and correlation matrix

We download the Guerry dataset, a collection of historical data used in support of 
Andre-Michel Guerry’s 1833 Essay on the Moral Statistics of France. The data set is hosted 
online in comma-separated values format (CSV) by the Rdatasets repository. We could download the file 
locally and then load it using read_csv, but pandas takes care of all of this automatically for us:

https://github.com/friendly/Guerry
                             OLS Regression Results                            
==============================================================================
Dep. Variable: Lottery R-squared: 0.414
Model: OLS Adj. R-squared: 0.392
Method: Least Squares F-statistic: 19.30
Date: Thu, 26 Jun 2025 Prob (F-statistic): 1.47e-09
Time: 17:35:22 Log-Likelihood: -375.28
No. Observations: 86 AIC: 758.6
Df Residuals: 82 BIC: 768.4
Df Model: 3
Covariance Type: nonrobust
================================================================================
coef std err t P>|t| [0.025 0.975]
--------------------------------------------------------------------------------
Intercept 194.3951 37.768 5.147 0.000 119.263 269.527
Wealth 0.2820 0.093 3.024 0.003 0.097 0.468
Literacy -0.3840 0.127 -3.033 0.003 -0.636 -0.132
np.log(Pop1831) -25.2363 6.047 -4.174 0.000 -37.265 -13.207
==============================================================================
Omnibus: 7.602 Durbin-Watson: 1.890
Prob(Omnibus): 0.022 Jarque-Bera (JB): 7.051
Skew: -0.651 Prob(JB): 0.0294
Kurtosis: 3.524 Cond. No. 1.13e+03
==============================================================================

Notes:
[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.
[2] The condition number is large, 1.13e+03. This might indicate that there are
strong multicollinearity or other numerical problems.
mX5 executed: 26/06/2025 17:35:23 Runtime: 0:0:47.680 Memload: 58% use
Partial Regression Plot Grid

https://spatialanalysis.github.io/geodaData/reference/guerry.html

Execstring('import statsmodels.api as sm; import numpy as np');

Execstr('model = smf.ols("Lottery ~ Wealth + Literacy + np.log(Pop1831)", data=df).fit()');
execstr('print(model.summary())');
execstr('sm.graphics.plot_partregress_grid(model)');

Statsmodels is a Python library designed for statistical modeling, hypothesis testing, and data exploration. It provides a wide range of statistical models, including linear regression, time series analysis, and generalized linear models. 
The library supports both formula-based modeling (similar to R) and direct use of NumPy arrays. The data science tutorial explains the so called AGSI data storage and his visualization of the timeline. AGSI is the Aggregated Gas Storage Inventory and offers you the possibility to be kept up to date whenever a new service announcement or update from one of our data providers is posted on the website.

Data representation of gas in storage as a timeline AGSI dataset.

https://blogs.embarcadero.com/why-a-data-scientist-chooses-delphi-for-powerful-real-world-visualizations/

Scikitlearns model.score(X,y) calculation works on coefficient of determination i.e R^2 is a simple functionthat takes model.score= (X_test,y_test). It doesn’t require y_predicted value to be supplied externally to calculate the score for you, rather it calculates y_predicted internally and uses it in the calculations.

  • Mean Function: Calculates the average of an array.
  • Covariance Function: Computes the covariance between two arrays.
  • Correlation: Uses covariance and standard deviations for the correlation coefficient.
  • ComputeCorrelationMatrix: Iterates through all variable pairs to compute corr-matrix.
  • PrintMatrix: Outputs the matrix to the console.

Delphi does not have a built-in correlation matrix function with a heatmap too, but you can implement one using standard math operations.

Guerry Dataset – from a csv file to a dataframe

The mrMath, mrStats, mrMatrix, mrImgUtils package includes:

  • Standard Fisher LDA classifier
  • Robust (and Fast Robust) version of this classifier
  • Incremental (and Robust) Fisher LDA classifier learning.
  • Support Vector Machines (least squares and lagrangian learning)
  • Naive Bayes
  • Simple Decission stumps
  • Radial basis function
  • C4.5 Decission trees.
  • K-means
  • Ensemble classifiers: AdaBoost, Gentle Boost, Bagging
  • Simple feed forward Neural Nets
mX5.2 with Statsmodels Console Output

Learn how to install statsmodels, a Python package for statistical modeling, using Anaconda, PyPI, source or development version.

Statsmodels Py 3.13.4

You can compute a correlation matrix in Delphi by iterating over all pairs of variables, extracting columns, and applying the Pearson correlation formula. For more advanced matrix operations or large datasets, consider using a Delphi matrix library.

procedure ComputeCorrelationMatrix(const Data: DMatrix; var CorrMatrix: DMatrix);
var
  i, j, k, nVars, nObs: Integer;
  colI, colJ: array of Double;
begin
  nObs:= Length(Data);
  nVars:= Length(Data[0]);
  //SetLength(CorrMatrix, nVars, nVars);
  SetMatrixLength(corrMatrix, nvars, nvars);
  for i:= 0 to nVars-1  do begin
    SetLength(colI, nObs);
    for j:= 0 to nObs - 1 do
      colI[j]:= Data[j][i];
    for j:= i to nVars-1  do begin
      SetLength(colJ, nObs);
      for k:= 0 to nObs - 1 do
        colJ[k]:= Data[k][j];
      CorrMatrix[i][j]:= PearsonCorrelation(colI, colJ);
      CorrMatrix[j][i]:= CorrMatrix[i][j]; // Matrix is symmetric
    end;
  end;
end;

To transform the CSV data from file to matrix and dataframe you need 4 steps:

S:= TStringList.Create;
  try
    //S.StrictDelimiter := True;
    S.LineBreak := #10;
    //S1.Delimiter := ',';
    s.loadfromfile(exepath+'\examples\1417_export_dataframe.csv');
    writ('size: '+itoa(s.count));
    SetMatrixLength(mData, 86, 6);
    TStringListToMatrix(s, mData);  

Input: The StringList contains rows of data as strings, separated commas.

Parsing: Each string is split into columns using CommaText of a temporary TStringList.

Matrix Population: The parsed values are stored in a 2D array (Matrix).

Output: The matrix is printed to verify the conversion.

procedure TStringListToMatrix(strList: TStringList; var matrix: DMatrix);
var i, j: Integer;
  RowData: TStringList;
begin
  if strList.Count = 0 then Exit;
  // Create a temporary TStringList to parse each row
  RowData:= TStringList.Create;
  try
    RowData.Delimiter:= ','; // Assuming comma-separated values
    RowData.StrictDelimiter:= True;
    //RowData.commatext
    // Resize matrix to match the TStringList dimensions
    SetLength(matrix, strList.Count);
    for i := 1 to strList.Count - 1 do begin
      RowData.DelimitedText:= strList[i];
      //writ('debug '+itoa(rowdata.count));
      SetLength(Matrix[i], RowData.Count);
      for j:= 4 to RowData.Count - 15 do begin   //slice 4-9
        Matrix[i][j-4]:= strtofloat(RowData[j]);
        //writ('debug '+flots(matrix[i][j]));
      end;
    end;
  finally
    RowData.Free;
  end;
end;
Partial Regression Plot with Statsmodels

debug: 208-RuntimeError: CPU dispatcher tracer already initlized 865 err:20
debug: 209-RuntimeError: CPU dispatcher tracer already initlized 865 err:20
Exception: RuntimeError: CPU dispatcher tracer already initlized at 865.3134

//# Fit an OLS regression model
  //eng.Execstring('model = smf.ols("Lottery ~ Literacy + np.log(Pop1831)", data=data).fit()');
   Execstr('model = smf.ols("Lottery ~ Wealth + Literacy + np.log(Pop1831)", data=df).fit()');
  //# Display the summary of results
   execstr('print(model.summary())');
  {Notice that there is one missing observation in the Region column. 
                  We eliminate it using a DataFrame method provided by pandas:}
   execstr('df = df.dropna()');
   execstr('sm.graphics.plot_partregress("Lottery","Wealth", ["Region","Distance"],'+
                                                     'data=df, obs_labels=False)');
   ExecStr('plt.show()');       
sample or observation tracer obs_labels=True

Scripts at:

https://sourceforge.net/projects/maxbox5/files/EKON29/1385_DCorrelation3SeabornPyCompare2_uc.txt/download

https://sourceforge.net/projects/maxbox5/files/examples/1417_statsmodels_64_delphi_python3.12.4debug30.txt/download

Python for Delphi at maXbox statsmodels console
Informatik Workshop 1994
2 Nation Locs France – Italy
Train your Main Brain
Museum near Rotterdam
EKON 29 Session

https://entwickler-konferenz.de/delphi-innovations-fundamentals/statistic-packages-fuer-delphi-oder-python

30 Jahre Delphi – 30 Jahre 4Gewinnt Gewinnspiel

You can find the script to run in maXbox VM

https://github.com/maxkleiner/maXbox5/blob/main/examples/170_4gewinnt_main3_2025.txt

Script: https://github.com/maxkleiner/maXbox5/blob/main/examples/4gewinnt2025.txt
Bug hunting in V5.2.9.196
CC 6572 Cité du Train – Mulhouse – France
The Heat Beat

Weatherapp5.4 with OpenWeathermap and OWM forecaster plus mapbox city maps

AKE AKE-Eisenbahntouristik
3 Nation Multisystem Locs – DB, B, SNCF – BB 181 212-2, BB 1608, CC 40110
ICE 411 (ICE-T) Hannover – Fulda, 24/08/2025

Char Statistic

So, for example, if passed “aAAbbbb” for ‘stones’ and “aA” for ‘jewels‘, the function should return 3.

function CommonLetters(S1,S2: string): integer;
{Count the number of letters in S1 are found in S2}
var i, j: integer;
begin
   result:=0;
   for i:=1 to Length(S1) do
    for j:=1 to Length(S2) do
     if S1[i]=S2[j] then Inc(result);
end;

procedure ShowJewelsStones(Memo: TMemo; Jewels,Stones: string);
{Show one Jewels-Stones comparison}
begin
   Memo2.Lines.Add(Jewels+' '+Stones+' '+IntToStr(CommonLetters(Jewels,Stones)));
end;

Both strings can contain any number of upper or lower case letters. However, in the case of ‘jewels’, all letters must be distinct.

const PYFUNC =
  'def countJewels(s, j):          '+LF+
  '  return sum(x in j for x in s) ';

with TPythonEngine.Create(Nil) do begin
  loadDLL;
  try
    ExecString('import sys');
    ExecString(PYFUNC);
    println('pyout:'+evalstr('countJewels("taAAbbbb","aA"),sys.version'));
    println('pyout:'+evalstr('countJewels("12345643","34"),sys.version'));
  except
    raiseError;
  finally
    unloadDll;
    Free;
  end;  
end;  

https://rosettacode.org/wiki/Jewels_and_stones#Python

TEE Capitole – Jouef CC 6526, Roco BB 9278, L.S. Models CC 6513
EKON 29

    result:= ‘GEO_Code Data Map Out: ‘+UTF8ToString(lStream.ReadString(lStream.Size));

mX52 SynEdit Upgrade
mX5.2.9.198 Upgrade
Tokyo Bay
EKON History

The slides for the session:

Click to access maxbox_starter157.pdf

Code Focus

This is a short story concerning the update of maXbox V5.2.8 with some code insights (8 Topics).

Release Notes maXbox 5.2.8.160 June 2025 mX528 beta64-bit🐞


  • py2,py3,py4,py5,py6,py7,py8(python3) enhanced template bds_delphi.dci
  • now 142 Tutorials last: Geocode Distance maxbox_starter142.pdf
  • dmath64.dll renew functions data science package
  • maxbox_starter_testsequence51.bat added listview events
  • new examples on https://sourceforge.net/projects/maxbox5/files/
  • ESC song available: examples/Sternenhaufen_Max_SunoAI.mp3
  • Issue BPM 123/124 has been released May 2025
  • source compatible of previous Version (see below)
  • update compatible for Python3.13 and Python3.14 P4D use
  • GO game menu/view/GoGame5 -TGoForm1-TGoBlock-TGoBoard

04.06.2025 10:17
Release Notes maXbox 5.2.8.160 June 2025
SHA1: 5.2.8.160 maXbox5.exe 6b80a390423dd7759fd4ae0f1df72700b82fffe8
SHA1: ZIP maxbox52.zip 531286300D531038FCB283FD713964EB24B26825

ListView Events

First we start with the listview enhancments. The OnCustomDrawXXX event handlers of Delphi’s TListView can be useful to make minor changes to the appearance of a list view control. They let developers avoid having to owner draw the control if they only want to make a few tweaks to its appearance.  OnCustomDraw allows drawing on the background of the list view control. We should handle this event if we want to draw or paint anything on the control’s background.

This example is much simpler than the preceding one. We will draw alternating list items in different colours, emulating green and white line printer paper. This is achieved by handing just the OnCustomDrawItem event as Listing 1 shows:

const
   cStripe = $CCFFCC;  // colour of alternate list items
procedure TForm1ListView1CustomDrawItem(Sender: TCustomListView;
                          Item: TListItem; State: TCustomDrawState;
                          var DefaultDraw: Boolean);
 begin
   if Odd(Item.Index) then
     // odd list items have green background
     environmentview.Canvas.Brush.Color:= cStripe
   else
     // even list items have window colour background
     environmentview.Canvas.Brush.Color:= clWindow;
 end;

Now we move on to demonstrate the OnCustomDrawSubItem event handler. Here we will display each list view column in a different colour.

https://sourceforge.net/projects/maxbox5/files/examples/1405_EnvironmentExampleMainForm2.pas/download

Geo Code Routines with OWM

Large Language Models (LLMs) are taking the world by storm, I mean you can not watch the news these days without a new LLM heating the market and causing waves, reshaping industries from healthcare to finance and even revolutionizing how we interact with spatial data.

But what does this mean for Geographic Information Systems (GIS) or image analysis? GIS has long been the backbone of spatial mapping, used in fields of environmental science. A new support function is the writeln(GetWeatherReport_OWM(‘Bern,CH’,’you API-Key’)); from OWM.

As a start to use OpenWeather products, we recommend our One Call API 3.0. For more functionality, please consider our products, which are included in professional collections.

OpenWeather provides hyperlocal minute-by-minute forecasts, historical data, current conditions, and weather forecasts ranging from short-term to annual for any location worldwide. All data is accessible via industry-standard APIs.

Instantly access weather data for any location worldwide with OpenWeather’s robust and practical products and APIs. Simply subscribe to our self-service automated products using your email and begin utilizing a range of forecasts, current conditions, historical data, alerts, and maps.

The primary function of an early warning system is to empower individuals and communities to take protective action before a hazard strikes. Studies have shown that providing just 24 hours’ notice of an impending hazardous event can reduce the ensuing damage by up to 30 percent. These systems bridge the gap between scientific forecasting and community preparedness, translating complex meteorological data into clear messages that can trigger life-saving responses. 

The internal direct function in maXbox5 use state of the art jSON and collection aspects to call the industrial Rest-API:

function GetWeatherReport(const City, ApiKey: string): string;
var
  HttpClient: THTTPClient;
  Response: IHTTPResponse;
  JsonResponse: TJSONObject;
  WeatherDescription: string;
begin
  HttpClient:= THTTPClient.Create();
  try
    // Replace with the OpenWeatherMap API endpoint
    Response:= HttpClient.Get(Format('https://api.openweathermap.org/data/2.5/weather?q=%s&appid=%s&units=metric', [City, ApiKey]));

    if Response.StatusCode = 200 then begin
      JsonResponse:= TJSONObject.ParseJSONValue(Response.ContentAsString) as TJSONObject;
      try
        // Extract weather description from JSON response
        WeatherDescription:= JsonResponse.GetValue<TJSONArray>('weather').Items[0].GetValue<string>('description');
        WeatherDescription:= WeatherDescription +', temp: '+floattostr(JsonResponse.GetValue<TJSONObject>('main').GetValue<double>('temp'));

        //Writeln('Weather in ', City, ': ', WeatherDescription);
        result:=  'Weather in '+ City +': '+ WeatherDescription;
      finally
        JsonResponse.Free;
      end;
    end
    else
      Showmessage('Failed to fetch weather data. HTTP Status: '+inttostr(Response.StatusCode));
  finally
    HttpClient.Free;
  end;
end;

Continuously refining its models using real-time data, OpenWeather delivers reliable forecasts worldwide, covering both remote and densely populated areas. https://openweathermap.org/guide

Image manipulation

In Delphi, the TBitmap class provides a method called CopyFromBitmap that allows you to copy the content of one bitmap to another. This is particularly useful when you want to duplicate or manipulate bitmap data. Here’s an example of how you can use it with your own needs:

function cropImage(originBitmap : TBitmap; Xpos, Ypos, width, height: integer): TBitmap;
   begin
     //result := TBitmap.Create;
     //result.Width:= Width;
     //result.Height:= Height;
     //result.CopyFromBitmap(originBitmap, TRect.Create(Xpos, Ypos, Xpos + Width, Ypos + Height), 0, 0);
  // Create the target bitmap
    result:= TBitmap.Create;
    try
      // Set the dimensions of the target bitmap
      result.Width:= Width;
      result.Height:= Height;
      // Copy the content from the source bitmap to the target bitmap
      result.Canvas.CopyRect(
        Rect(0, 0, result.Width, result.Height),
        originBitmap.Canvas,
        Rect(xpos, ypos, originBitmap.Width, originBitmap.Height)
      );
    finally
       originBitmap.Free;
    end;
   end;
  • Key Points:
  • Initialization: Ensure both bitmaps are properly initialized and have the desired dimensions.
  • Copying: Use Canvas.CopyRect to copy the content from one bitmap to another.
  • Memory Management: Always free the bitmaps after use to avoid memory leaks.
Compile the V5.2.8.160

The GO Board

Go is one of those simple but complex board games.  Two opponents take turns placing black and white stones  on a square board.  If you surround a group of opponents stones with yours, the stones are removed and you get credited with a point for each stone captured.  

If you are  not familiar with the game just do a web search on “Go game rules” or “Go game tutorial” and you’ll find plenty of sites.  We with D4F integrated the game in this maXbox. Identifying groups of stones and determining when a group was surrounded by stones of a the opposite color was harder to code than expected . 

The game is played by placing stones on the intersections of gridlines.  A group is a set of one or more stones of the same color connected by horizontal and vertical grid lines.  A group is captured by surrounding it with  stones of the opposite color.  “Surrounding”  means that each horizontal and vertical grid line extending from the edges of a group is filled with a stone of  the opposite color.  

System and CPU Information 

In Delphi, the FastLocate2Bytes function is often used for optimized searching of a two-byte sequence within a larger data block. While Delphi itself doesn’t have a built-in FastLocate2Bytes function, you can implement a highly efficient version tailored for 64-bit systems by leveraging modern CPU instructions and memory alignment.

Here’s an example implementation for a 64-bit environment:
This implementation is straightforward and works well for most cases. If you need even faster performance for large datasets, consider using SIMD (Single Instruction, Multiple Data) or platform-specific optimizations like AVX2 instructions. To measure such things we updated the JCLSysInfo Library.

https://github.com/project-jedi/jcl/blob/master/jcl/source/common/JclSysInfo.pas

function GetEnvironmentVarsX(const Vars: TStrings; Expand: Boolean): Boolean;
var
  Raw: PChar;
  Expanded: string;   I: Integer;
begin
  Vars.BeginUpdate;
  try
    Vars.Clear;
    Raw:= GetEnvironmentStrings;
    try
      MultiSzToStrings(Vars, Raw); fix
      Result:= True;
    finally
      FreeEnvironmentStrings(Raw);
    end;
    if Expand then begin
      for I:= 0 to Vars.Count - 1 do begin
        Expanded:= Vars[I];
        if ExpandEnvironmentVar(Expanded) then
          Vars[I]:= Expanded;
      end;
    end;
  finally
    Vars.EndUpdate;
  end;
end;
https://metadefender.com/results/file/bzI1MDYwM2pod1RlWUZLeTZUOTV1RWhzWjd6ZG0_mdaas
https://metadefender.com/results/file/bzI1MDYwNnZ3anRnZlozX18yczFPaV9nZ244_mdaas

Python Updates

To get compatible with Python 3.13 and 3.14 some small engineering was done. It was only meant to be release day for 3.13.4 today, but poor number 13 looked so lonely… And hey, we had a couple of tarfile CVEs that we had to fix. So most of the Release Managers and all the Developers-in-Residence (including Security Developer-in-Residence Seth Michael Larson) came together to make it a full release party.

https://www.python.org/

UTF8 Detection

There is no 100% save way to detect UTF-8 streams. The bigger MinimumCountOfUTF8Strings, the lower is the probability of a false positive. On the other hand, a big MinimumCountOfUTF8Strings
makes it unlikely to detect files with only little usage of non US-ASCII chars, like usual in European languages.

The following checks for a BOM in UTF-8 format or searches the first 4096 bytes for typical UTF-8 octet sequences:

function IsUTF8(Stream: TStream; out WithBOM: Boolean; BytesToCheck: integer): Boolean;
var
  Buffer: TBytes;
  BufferSize, BomLen: Integer;
  Encoding: TEncoding;
begin
  // if Stream is nil, let Delphi raise the exception, by accessing Stream,
  // to signal an invalid result

  // start analysis at actual Stream.Position
  BufferSize:= Min(BytesToCheck, Stream.Size - Stream.Position);

  // if no special characteristics are found it is not UTF-8
  Result:= False;
  WithBOM:= False;

  if BufferSize > 0 then  begin
    SetLength(Buffer, BufferSize);
    Stream.Read(Buffer, 0, BufferSize);
    Stream.Seek(-BufferSize, soCurrent);
    { first search for BOM }
    Encoding:= nil;
    BomLen:= TEncoding.GetBufferEncoding(Buffer, Encoding);
    WithBOM:= BOMLen > 0;
    if Encoding = TEncoding.UTF8 then
      Exit(True)
    else if WithBom then
      Exit(False);
    { Now check the content for UTF8 sequences }
    Result:= IsUtf8(Buffer, 0, BytesToCheck);
  end;
end;

Minitrix BR 110

Code Organisation

4 Nation Locs – LS.Models, Märklin, Liliput, Rivarossi

All Tutorials so far:

Tutorial 00 Function-Coding (Blix the Programmer)
Tutorial 01 Procedural-Coding
Tutorial 02 OO-Programming
Tutorial 03 Modular Coding
Tutorial 04 UML Use Case Coding
Tutorial 05 Internet Coding
Tutorial 06 Network Coding
Tutorial 07 Game Graphics Coding
Tutorial 08 Operating System Coding
Tutorial 09 Database Coding
Tutorial 10 Statistic Coding
Tutorial 10 Probability Coding
Tutorial 11 Forms Coding
Tutorial 12 SQL DB Coding
Tutorial 13 Crypto Coding
Tutorial 14 Parallel Coding
Tutorial 15 Serial RS232 Coding
Tutorial 16 Event Driven Coding
Tutorial 17 Web Server Coding
Tutorial 18 Arduino Coding and Web of Things
Tutorial 18_3 Arduino RGB LED Coding Breadboard and Source LED Zip
Tutorial 18_5 Arduino RGB LED WebSocket
Tutorial 19 WinCOM /Arduino Coding and Source LED COM
Tutorial 20 Regular Expressions RegEx
Tutorial 20_1 RegEx PI Report
Tutorial 20_2 BASTA 2015 RegEx Slides
Tutorial 21 Android Coding (coming 2015)
Tutorial 21 Android SONAR: End of 2015
Tutor 21 Android SONAR: 2015 & Basta LED Things & Code ADK SeekBar
Tutorial 22 Services Coding
Tutorial 23 Real Time Systems
Tutorial 24 Clean Code
Tutorial 25 maXbox Configuration
Tutorial 26 Socket Programming with TCP
Tutorial 27 XML & Tree
Tutorial 28 DLL Coding (available)
Tutorial 29 UML Scripting (available)
Tutorial 30 Web of Things & Basta 2014 Arduino & maXbox
Tutorial 31 Closures (2014)
Tutorial 32 SQL Firebird (2014)
Tutorial 33 Oscilloscope (2014)
Tutorial 34 GPS Navigation (2014)
Tutorial 35 WebBox (2014)
Tutorial 36 Unit Testing (2015)
Tutorial 37 API Coding (2015)
Tutorial 38 3D Coding (2015)
Tutorial 39 GEO Map Coding (available)
Tutorial 39_1 GEO Map OpenLayers (available)
Tutorial 39_2 Maps2 Coding
Tutorial 40 REST Coding (2015)
Tutorial 40_1 OpenWeatherMap Coding German
Tutorial 41 Big Numbers Coding (2015)
Tutorial 41 Big Numbers Short
Tutorial 42 Multi Parallel Processing (2015)
Tutorial 43 Code Metrics: June2016
Tutor 43_1 Code Metrics II
Tutorial 44 IDE Extensions
Tutorial 45 Robotics: July2016
Tutorial 46 WineHQ: Dez2016
Tutor 47 RSA Crypto Jan2017
Tutor 48 Microservice Jan2017
Tutorial 49 Refactoring: March 2017
Tutorial 50 Big Numbers II: April 2017
Tutorial 51 5 Use Cases April 2017
Tutorial 52 Work with WMI Mai 2017
Tutorial 52_2 Work with WMI II June 2017
Tutorial 53 Real Time UML August 2017
Tutorial 54 MicroserviceII MS Crypto API Sept 2017
Tutorial 55 ASCII Talk Dez 2017
Tutorial 56 Artificial Neural Network 2018
Tutorial 57 Neural Network II
Tutorial 58 Data Science
Tutorial 59 Big Data Feb 2018
Tutorial 60 Machine Learning March 2018
Tutorial 60_1 Sentiment Analysis
Tutorial 60_2 Neural Network III
Tutorial 63 Machine Games
Tutorial 64 Install Routines
Tutorial 65 Machine Learning III
Tutorial 66 Machine Learning IV
Tutorial 67 Machine Learning V
Tutorial 68 Machine Learning VI
Tutorial 69 Machine Learning VII
Tutorial 70 NoGUI Shell Code
Tutorial 71 CGI and Web Sockets
Tutorial 72 Multilanguage Coding
Tutorial 73 EKON 24 Community Edition
Tutorial 74 BASTA 2020 VS Code Vision
Tutorial 75 Machine Learning VIII Object Detection
Tutorial 76 Machine Learning IX with CAI
Tutorial 77 Machine Learning X Confusion Matrix
Tutorial 78 Portable pixmap format (PPM)
Tutorial 79 Unit Testing with Asserts
Tutorial 80 My Tips & Tricks
Tutorial 81 RSS Feeds of BBC March 2021
Tutorial 82 JSON Code April 2021
Tutorial 82_2 JSON Sentiment Analysis API April 2021
Tutorial 83 Machine Learning XI Classification April 2021
Tutorial 84 Machine Learning XII Baseline Mai 2021
Tutorial 85 JSON Automation JSON4Delphi Mai 2021
Tutorial 86 Python4Delphi June 2021
Tutorial 86_1 Python4Delphi July 2021
Tutorial 86_2 Python4Delphi July 2021
Tutorial 86_3 Python4maXbox July 2021
Tutorial 86_4 Python4maXbox II
Tutor 86_5 Germany
Tutorial 87 CAI Image Detection in Lazarus September 2021
Tutorial 88 Performance Tuning Oct. 2021
Tutorial 89 Build a CNN Oct. 2021
Tutorial 89_1 Build a CNN Validation Nov. 2021
Tutorial 89_2 Build a CNN Prediction Nov. 2021
Tutorial 90 Python Pascal CheatSheet Nov. 2021
Tutorial 91 Faker SynDat Generator Dez. 2021
Tutorial 91_1 Faker SynDat II, Python_CAI CheatSheet Jan. 2022
Tutor 92 Big Decimals How to demystify PI
Tutorial 92_1 DelphiVCL4Python Feb. 2022
Tutorial 92_2 Geocoding March 2022
Tutorial 93 Geocoding II April 2022
Tutorial 94 Post Service API April 2022
Tutorial 95 Translator API April 2022
Tutorial 96 CNN Process Pipeline July 2022
Tutorial 97 Operating System Routines August 2022
Tutorial 98 Integration Python Scripts August 2022
Tutorial 99 DataScience API October 2022
Tutorial 100 Data Science Story November 2022
Tutorial 101 Data Science Story2 December 2022
Tutorial 102 Compiler and Interpreter December 2022
Tutorial 103 Image to Text API January 2023
Tutorial 104 Restcountries API January 2023
Tutorial 105 Classify CNN February 2023
Tutorial 106 Air Distance and Bearing, March 2023
Tutorial 107 pas2js, March 2023
Tutorial 108 Hacking your M rklin, March 2023
Tutorial 109 Google Translate API, April 2023
Tutorial 109_1 OpenAI ChatGPT API, April 2023
Tutorial 110 Code Overview Samples, April 2023

Tutor 110 Code Overview Samples, April 2023
Tutor 111 Pas2JS, August 2023
Tutor 112 Machine Learning Package, August 2023
Tutor 113 Migrate to 64-bit Report, October 2023
Tutor 114 Cannonball Simulation, September 2023
Tutor 115 64-bit 2 Points in Space, November 2023
Tutor 116 64-bit 2 Debugging, December 2023
Tutor 117 Mystery of IStream, December 2023
Tutor 118 Code Signing, January 2024
Tutor 119 Multicode_Programming, February 2024
Tutor 119 Multicode_2, February 2024
Tutor 120 Unicode_Signs, March 2024
Tutor 121 Geocoding IV, March 2024
Tutor 122 Geocoding V, March 2024
Tutor 123 OCR NeuralNet, March 2024
Tutor 124 IMage API, April 2024
Tutor 125 Modern Regex, May 2024
Tutor 126 4 Machine Learning Object Detection Solutions, July 2024
Tutor 127 Geo Maps Directions Station2Station, October 2024
Tutor 128 Working with perplexity.ai, October 2024
Tutor 129 Using WebView2, October 2024
Tutor 130 MIDI magic music, November 2024
Tutor 131 Test Classifier App, December 2024
Tutor 132 Dragon Curve Sound, December 2024
Tutor 133 The Art of Connection, January 2025
Tutor 134 Beyond the Obstacle, January 2025
Tutor 135 Top 7 Algorithm, February 2025
Tutor 136 Google Gemini API, February 2025
Tutor 137 Lambda_expressions.pdf, February 2025
Tutor 138 Top 7 Statistical Methods.pdf, March 2025
Tutor 139 Top 5 Diagram Types, March 2025
Tutor 140 Data Correlation Analysis, March 2025
Tutor 141 Multi Pascal Solver, April 2025
Tutor 142 Geocode Distance Data Art, May 2025
Tutor 143 Go Game Board, June 2025
Tutor 144 Code Focus, June 2025
Tutor 145 Services, June 2025
Tutor 146 Debugging, June 2025
Tutor 147 Weather Station, June 2025

http://www.softwareschule.ch/examples/earthscript.htm

Delphi Summit Amsterdam June 2025
http://www.softwareschule.ch/download/maxbox_starter148.pdf

## Summary Table: Notable Changes

| Feature/Aspect                  | 5.2.9.170 (June 2025)                | Previous Versions (e.g., 5.1.4.98)      |
|——————————|————————————–|———————————|
| Python Version Support     | Python 3.13, 3.14, enhanced templates| Older Python versions, fewer templates  |
| Tutorials                         | 145, new geocode distance tutorial    | Fewer (less than 142)                   |
| Data Science Functions      | Renewed in dmath64.dll                | Previous function set                   |
| Example Projects                | New examples added                    | Existing examples only                 |
| Game Features                   | Go game integration                   | Not present                              |
| REST API/JSON Handling   | State-of-the-art, improved            | Less advanced                            |
| Performance Optimization | Updated for 64-bit, JCLSysInfo        | Previous optimizations                 |
| Backward Compatibility      | Maintained                            | N/A                                      |

Early Binding and Late Binding

Early Binding (compile-time time polymorphism) As the name indicates, compiler (or linker) directly associate an address to the function call. It replaces the call with a machine language instruction that tells the mainframe to leap to the address of the function.

Late Binding : (Run time polymorphism) In this, the compiler adds code that identifies the kind of object at runtime then matches the call with the right function definition.

Show this in two snippets with the same purpose, to make a Rest-Call to the Gemini API:

function TRestClient4_AskChatGPTGemini_Earlybinding(askstream, tempera: string; 
                                               aResponseHeader:TRestResponseHandler):string;
var JPostdat: string; jo: TJSON;
    restc: TRestResource; stream: TStringStream; jArray:TJsonArray2;
begin
    JPostDat:= '{'+
    '"contents": [{'+
    '"parts": [{"text": "%s"}]}],  '+
    '"generation_config": {        '+
    '  "temperature": "%s",        '+
    '  "max_output_tokens": 550    '+
    '   }                          '+
    '}';  
  with TRestClient.create(self) do begin
     restc:= Resource('https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?'+
                                                          'key='+GEMINI_APIKEY);
     println('@addr:'+objtostr(restc))
     restc.ContentType('application/json');
     ConnectionType:= hctWinInet;
     OnResponse:= @TRestOnResponseEvent2;
     try
       jo:= TJSON.Create(); 
       stream:= TStringStream.create('');
       stream.writestring(format(JPostDat,[askstream,tempera]));
       jo.parse(restc.Post(stream))
       jArray:= jo.values['candidates'].asarray[0].asobject['content'].asobject['parts'].asarray;
       result:= JArray[0].asobject['text'].asstring;
     finally
       Free;   //restclient dispose
       jo.Free;
       stream.free;
     except  
       writeln('EWI_Except:'+ExceptiontoString(exceptiontype,exceptionparam));
     end; 
  end; //with   
end; 

Late Binding, A virtual function is a member function that is declared in the base class using the keyword virtual and is re-defined (Overridden) in the derived class. It tells the compiler to perform late binding where the compiler matches the object with the right called function and executes it during the runtime. This technique falls under Runtime Polymorphism.:

function GEmini_API6_Latebinding(AURL, askstream, tempera: string): string;
var
  httpReq,hr: Olevariant;
  jArray: TJsonArray2;
  jo: TJSON;  JPostdat: string;
begin
  Result:= '';
  JPostDat:= '{'+
    '"contents": [{'+
    '"parts": [{"text": "%s"}]}],  '+
    '"generation_config": {        '+
    '  "temperature": "%s",        '+
    '  "max_output_tokens": 550    '+
    '   }                          '+
    '}';  
  // Use JSON for REST API calls and set API KEY via requestheader
  httpReq:= CreateOleObject('WinHttp.WinHttpRequest.5.1');
  jo:= TJSON.Create();
  try             
    hr:= httpReq.Open('POST', 
           'https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?'+
                                                          'key='+GEMINI_APIKEY, false);
    // Select HTTPS POST method, set POST data, specify endpoint URL
    httpReq.setRequestheader('content-type','application/json'); 
    if hr= S_OK then HttpReq.Send(format(JPostDat,[askstream,tempera]));
    If HttpReq.Status = 200 Then
       result:= HttpReq.responseText
    Else result:= 'Failed getresponse:'+itoa(HttpReq.Status)+HttpReq.responseText;
      writeln('debug response '+HttpReq.GetAllResponseHeaders); 
    jo.parse(result) 
    jArray:= jo.values['candidates'].asarray[0].asobject['content'].asobject['parts'].asarray;
    result:= JArray[0].asobject['text'].asstring;
  finally
    jo.Free;
    httpreq:= unassigned;  
  end;                
end;
3 Nation Locs F-CH-A

Core Matrix

procedure CalculateCorrelationMatrix(data: DMatrix; var matrix: DMatrix);
var i, j, n: Integer;
begin
  n:= Length(data);
  for i:= 0 to n - 1 do begin
    for j:= 0 to n - 1 do 
      matrix[i][j]:= {Pearson}Correlation(data[i], data[j]);
  end;
end;

The correlation matrix below shows the correlation coefficients between several variables related to education: Each cell in the table shows the correlation between two specific variables. For a better transfer you need a conversion from a list to a matrix called dataframe:

 Type TMatrx = array of array of string; 
      DMatrix = array of array of double;

procedure TStringListToMatrix(strList: TStringList; var matrix: TMatrx);
var i, j: Integer;
  RowData: TStringList;
begin
  if strList.Count = 0 then Exit;
  // Create a temporary TStringList to parse each row
  RowData:= TStringList.Create;
  try
    RowData.Delimiter:= ','; // Assuming comma-separated values
    RowData.StrictDelimiter:= True;
    
    // Resize matrix to match the TStringList dimensions
    SetLength(matrix, strList.Count);
    for i := 0 to strList.Count - 1 do begin
      RowData.DelimitedText:= strList[i];
      //writ('debug '+itoa(rowdata.count));
      SetLength(Matrix[i], RowData.Count);
      for j:= 0 to RowData.Count - 1 do
        Matrix[i][j]:= RowData[j];
    end;
  finally
    RowData.Free;
  end;
end;
https://entwickler-konferenz.de/delphi-innovations-fundamentals/statistic-packages-fuer-delphi-oder-python/
Partial Regression of Guerry Dataset
                            OLS Regression Results                            
==============================================================================
Dep. Variable: Lottery R-squared: 0.414
Model: OLS Adj. R-squared: 0.392
Method: Least Squares F-statistic: 19.30
Date: Sun, 29 Jun 2025 Prob (F-statistic): 1.47e-09
Time: 16:59:33 Log-Likelihood: -375.28
No. Observations: 86 AIC: 758.6
Df Residuals: 82 BIC: 768.4
Df Model: 3
Covariance Type: nonrobust
===================================================================================
coef std err t P>|t| [0.025 0.975]
-----------------------------------------------------------------------------------
Intercept 194.3951 37.768 5.147 0.000 119.263 269.527
Wealth 0.2820 0.093 3.024 0.003 0.097 0.468
Literacy -0.3840 0.127 -3.033 0.003 -0.636 -0.132
np.log(Pop1831) -25.2363 6.047 -4.174 0.000 -37.265 -13.207
==============================================================================
Omnibus: 7.602 Durbin-Watson: 1.890
Prob(Omnibus): 0.022 Jarque-Bera (JB): 7.051
Skew: -0.651 Prob(JB): 0.0294
Kurtosis: 3.524 Cond. No. 1.13e+03
==============================================================================
http://www.softwareschule.ch/examples/weatherstation52.htm

Multi Pascal Solver

sphenic number is a positive integer that is the product of three distinct prime numbers. More technically it’s a square-free 3-almost prime (see Related tasks below).

For the purposes of this task, a sphenic triplet is a group of three sphenic numbers which are consecutive.

I want to show the solution from rosettacode in five language variants:

  1. Pascal
  2. Python
  3. Free Pascal
  4. Free Pascal TIO Web
  5. Delphi

Note that sphenic quadruplets are not possible because every fourth consecutive positive integer is divisible by 4 (= 2 x 2) and its prime factors would not therefore be distinct. Example

30 (= 2 x 3 x 5) is a sphenic number and is also clearly the first one. Lets start with Object Pascal in maXbox5 Editor:

Result in maXbox Console
procedure CreateSphenics(const pr: TInt64Array{tarrElements});
var
  i1,i2,i3,
  idx1,idx2,
  p1,p2,pp,cnt : Uint32;
begin
  cnt:= 0;
  pp:= trunc(exp(1/3*ln(LLimit)));
  idx1:= binary_search(pp,Pr)-1;
  i1:= 0;
  writeln('last prime: '+itoa(pr[high(pr)])+' of primes: '+itoa(high(pr)));
  repeat
    p1 := pr[i1];
    pp:= trunc(sqrt(LLimit DIV p1));
    idx2:= binary_search(pp,Pr)+1;
    For i2:= i1+1 to idx2 do begin
      p2:= pr[i2]*p1;
      For i3:= i2+1 to High(pr) do begin
        pp:= Pr[i3]*p2;
        if pp > LLimit then
          break;
        //mark as sphenic number
        PrimeSieve[pp]:= true;    //todo -done
        //primes[pp]:= 1;
        inc(cnt);
      end;
    end;
    inc(i1);
  until i1>idx1;
  //insert
  setlength(sphenics,cnt);
  pp:= 0;
  For i1:= 0 to LLimit do begin
    if primeSieve[i1] then begin
      sphenics[pp]:= i1;
      inc(pp);
    end; 
  end;
  //primeSieve.Free;
end;

Most of the time, ~ 75% in this case, is spent with sort. So i put in maXbox processmessagesOFF; and processmessagesON; between binary search to speed up and Now changed to use sieve of erathostenes and insert sphenic numbers in that array, as you can see dynamic arrays are the main storage:

const
  LLimit= 1000*1000;  // *1000;
  
type
  tPrimesSieve = array of boolean;
  ttElement = Uint32;
  tarrElements = array of ttElement;
  
var
  PrimeSieve : tPrimesSieve;
  primes : TInt64Array; // object prefilled //tarrElements;
  sphenics : tarrElements; 

We also use a class TPrimes for the primes array sieve, so its also Object Pascal:

try
  ClearAll;
  Sieve:=TPrimes.Create;
  primes:= sieve.prime;
  setlength(primes,78500);
  setlength(PrimeSieve,LLimit+1);// inits with #0
  CreateSphenics(Primes);   //must be the filled primes
finally
  Sieve.Free;
end; 
Sphenic Numbers

Next will be the Python one as Python4Delphi in maXbox5:

""" rosettacode.org task Sphenic_numbers """
//https://rosettacode.org/wiki/Sphenic_numbers#Python

from sympy import factorint

sphenics1m, sphenic_triplets1m = [], []

for i in range(3, 1_000_000):
    d = factorint(i)
    if len(d) == 3 and sum(d.values()) == 3:
        sphenics1m.append(i)
        if len(sphenics1m) > 2 and i - sphenics1m[-3] == 2 and i - sphenics1m[-2] == 1:
            sphenic_triplets1m.append(i)

print('Sphenic numbers less than 1000:')
for i, n in enumerate(sphenics1m):
    if n < 1000:
        print(f'{n : 5}', end='\n' if (i + 1) % 15 == 0 else '')
    else:
        break

print('\n\nSphenic triplets less than 10_000:')
for i, n in enumerate(sphenic_triplets1m):
    if n < 10_000:
        print(f'({n - 2} {n - 1} {n})', end='\n' if (i + 1) % 3 == 0 else '  ')
    else:
        break

print('\nThere are', len(sphenics1m), 'sphenic numbers and', len(sphenic_triplets1m),
      'sphenic triplets less than 1 million.')

S2HK = sphenics1m[200_000 - 1]
T5K = sphenic_triplets1m[5000 - 1]
print(f'The 200_000th sphenic number is {S2HK}, with prime factors {list(factorint(S2HK).keys())}.')
print(f'The 5000th sphenic triplet is ({T5K - 2} {T5K - 1} {T5K}).')

And it will be of course the same result and interesting almost the same performance (~12 seconds):

There are 206964 sphenic numbers and 5457 sphenic triplets less than 1 million.
The 200_000th sphenic number is 966467, with prime factors [17, 139, 409].
The 5000th sphenic triplet is (918005 918006 918007).
mX5🐞 executed: 03/04/2025 10:04:44 Runtime: 0:0:13.64 Memload: 75% use

In Python4Delphi we import extra libaries with execstr:

procedure Delphi9_PySolution(loc: string);
var Data1, Data2 : array of Double; 
begin
  with TPythonEngine.Create(Nil) do begin
   //pythonhome:= PYHOME64;
   // -V:3.12 *   Python 3.12 (64-bit)
   loadDLL;
   autofinalize:= false;
   try
    execstr('import io, sys  # Added')
    execstr('output = io.StringIO()') 
    execstr('sys.stdout = output');  
    execstr('from sympy import factorint');
    execstr('sphenics1m, sphenic_triplets1m = [], []');

Next is a solution of the web therefore it runs in a browser:

Call of tio.run from maXbox5 generator to invoke the Free Pascal Compiler:

The web server of Try It Online and the arenas (where user code is executed) are currently run on three separate servers. TIO is getting more and more traffic, so additional arenas will be required. Also, server-side permalinks will eventually require a separate storage. With your help, I hope to ensure a smooth operation of all TIO services.

TIO is powered by DigitalOcean. Their virtual private servers are affordable, fast, scalable, and (most importantly) professionally managed. The TIO web app is free of charge, ad-free, and doesn’t use tracking cookies or third-party analytic scripts.

https://tio.run/#

The last solution is the Delphi one, not finished yet with further tests and profiling. The TPrimes class introduced has been enhanced to include the GetPrevPrime and GetNthPrime function and moved into a MathsLib unit  which is included here with the source code zip file and is also now included in our common library file DFFLIBV04.  The array of int64 will be filled with 78499 primes up to the last one 1,000,003 as the range of one million. There are exactly 78,498 prime numbers between 1 and 1,000,000. This count has been determined using mathematical methods such as the Prime Number Theorem, which estimates the density of primes below a given number.

In maXbox the class and library is precompiled so you dont need to install or import it.

Sieve:= TPrimes.Create;
  prime:= sieve.prime;
  writeln(itoa(prime[78499])+'  '+itoa(high(prime)));
  for it:=1 to 50 {Sieve.MaxPrimeInTable-1} do
     //write(itoa(Sieve.GetNthPrime(It))+' ');
     write(itoa(prime[It])+' ');
  sieve.free;
  GetSphenicNumbers(Sphenic);
  Memo2.Lines.Add('Some Sphenic numbers less than 1,000:');
  S:='';
  for i:=0 to 1000-1 {High(Sphenic)} do begin
     if Sphenic[i]>993 then break;
     S:=S+Format('%4d',[Sphenic[i]]);
     if (i mod 15)=14 then S:=S+CRLF;
   end;
  writeln(S); 
  writeln('Total Sphenic Numbers found = '+
      FloatToStrF(Sphenic[Length(Sphenic)-1]-800,ffNumber,18,0));

In number theory, a sphenic number (from Greek: σφήνα, ‘wedge’) is a positive integer that is the product of three distinct prime numbers. Because there are infinitely many prime numbers, there are also infinitely many sphenic numbers. The cyclotomic polynomials Φn(x){\displaystyle \Phi _{n}(x)}, taken over all sphenic numbers n, may contain arbitrarily large coefficients[1] (for n a product of two primes the coefficients are ±1{\displaystyle \pm 1} or 0).

Any multiple of a sphenic number (except by 1) is not sphenic. This is easily provable by the multiplication process at a minimum adding another prime factor, or raising an existing factor to a higher power.

Solutions Overview of Math Solver

  • 1 Internal Pascal code scripting in maXbox5
  • 2 External call of Python for Delphi (P4D)
  • 3 Internal Free Pascal Compiler & Lazarus API
  • 4 External call of Free Pascal TIO Web
  • 5 Internal script (precompiled Delphi VM)

Conclusion

When it comes to problem-solving, there are often multiple solutions that can be used to solve the same problem. The choice of solution depends on various factors such as performance, storage, correctness, implement-ation, accessibility, simplicity, and also scaleability and security in different environments. The code is more or less the same but the choice of the environment (script, executable, container, hosting, web or cloud API) could be a response of different requirements.

In number theory, a sphenic number (from Greek: σφήνα, ‘wedge’) is a positive integer that is the product of three distinct prime numbers. Because there are infinitely many prime numbers, there are also infinitely many sphenic numbers.

The reasons of code performance optimization

Optimizing code performance is critical for many reasons:

  • Enhanced user experience: Faster code execution enables better response times and more efficient resource usage, resulting in glad end-users.
  • Scalability: Optimized code can handle substantial workloads, allowing apps to scale nice with increased demand and generate higher satisfaction.
  • Reduced costs: Efficient code makes more use of computing resources, which also minimizes costs for infrastructure and cloud-based services.

The Script you can find at: https://sourceforge.net/projects/maxbox5/files/examples/1390_Sphenic_Numbers2TIO_12_py_uc.txt/download

https://rosettacode.org/wiki/Sphenic_numbers#Delphi

Primes Pentart
3 Nation Locs
4 Nations – BB 9278 SNCF, E 444.105 FS, SBB Re 4/4 II 11253, ÖBB Rh 1042.10
4 Nation TEE Locs: DB E10 1312, SBB Re 4/4 II 11160, FS E 656 1A, NS BB 1104
Les 3 CC 6500 en 3 Epoque

Here’s another program to download, IntPowerDemo.  It calculates integer power of a real number using 4 different techniques, brute force, recursive, powers of 2, and Delphi’s IntPower function.   QueryPerformanceCounter procedure  is used to calculate the time for each method.  (Even the slowest calculates 1.525  about one million times per second on my medium speed PC.)  

https://sourceforge.net/projects/maxbox5/files/examples/1394_IntPower.txt/download

Nominatim OpenStreetMap Platform

This sample uses Nominatim OpenStreetMap Platform services. Nominatim uses OpenStreetMap data to find locations on Earth by name and address (geocoding). It can also do the reverse, find an address for any location on the planet.

https://nominatim.org/

const GEOLOCURL9 = 'https://nominatim.openstreetmap.org/search?format=json&q=%s';
      URL_APILAY_GEO = 'https://api.apilayer.com/geo/country/capital/%s';  

function API_GEOLocation_OSM9(AURL, aloc, aApikey: string): Tlatlong;
var Httpreq: THttpRequestC; httpres: string;
    jsn: TMcJsonItem;
begin
  httpreq:= THttpRequestC.create(self);
  httpreq.headers.add('Accept: application/json; charset=utf-8');
  //httpreq.headers.add('X-Api-Key:'+aAPIkey);
  //httpreq.SecurityOptions:= [soSsl3, soPct, soIgnoreCertCNInvalid];
  httpreq.useragent:= 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1'; 
  try
    if httpreq.get(Format(AURL,[aloc])) then begin
       httpres:= (httpreq.Response.ContentAsUTF8String)
       //writeln('conttype '+httpreq.Response.ContentType);
       writ('debug back '+formatJson(httpres));
       jsn:= TMcJsonItem.Create;
       jsn.AsJSON:= httpres;
       result.lat:= jsn.at(0,'lat').asnumber;
       result.long:= jsn.at(0,'lon').asnumber;
       result.descript:= Format('Coords: lat %2.5f  lng %2.5f %s osm_id: %s ',
                                [result.lat,result.long,jsn.at(0,'name').asstring,
                                                        jsn.at(0,'osm_id').asstring]); 
    end else Writeln('APIError '+inttostr(Httpreq.Response.StatusCode2));
  except  
    writeln('EWI_APIHTTP: '+ExceptiontoString(exceptiontype,exceptionparam));  
  finally  
    writeln('Status3: '+gethttpcod(httpreq.Response.statuscode2))
    httpreq.Free;  
    sleep(200);
    jsn.Free;
  end; 
end;

Nominatim can power the search box on your website, allowing your users to type free-form queries (“Cafe Paris, New York”) in any language. It also offers a structured query mode (“postcode=12345”, “city=London”, “type=cafe”) that helps you to automate geocoding of extensive address lists.

t_latlong:= API_GEOLocation_OSM9(GEOLOCURL9, ‘Gare du Nord, Paris, France’, ‘L_APIKEY’);

writ(jsonunescape((t_latlong.descript),#13#10));   

Status3: SC_OK
Coords: lat 48.88140 lng 2.35744 Gare du Nord (RER) osm_id: 5230752679
mX5🐞 executed: 17/04/2025 11:11:25 Runtime: 0:0:2.798 Memload: 46% use

OpenWeb(‘https://www.latlong.net/c/?lat=’+flots(t_latlong.lat)+’&long=’+flots(t_latlong.long));

C:\maxbox\maxbox5\examples\1274_GoogleMapsAPI_General1.pas
https://sourceforge.net/projects/maxbox5/files/examples/1274_GoogleDirForm2GeocodeWeather_General_Paros.pas/download
TEE-Time DB
Nostalgie Sonderzug Koblenz-Winterberg

Quelle: https://www.bahnbilder.de/1200/111-001-4-mit-tee-sonderzug-949517.jpg

https://sourceforge.net/projects/maxbox5/files/examples/1397_Geolocation_distance_uc.txt/download
const URL_GEOLOCURL9 = 'https://nominatim.openstreetmap.org/search?format=json&q=%s';
      URL_APILAY_GEO = 'https://api.apilayer.com/geo/country/capital/%s';  
      
var fromgeo, togeo: Tlatlong;      
 
function API_GEOLocation_OSM9(AURL, aloc, aApikey: string;
                                             verbose: boolean): Tlatlong;
var Httpreq: THttpRequestC; httpres: string;
    jsn: TMcJsonItem;
begin
  httpreq:= THttpRequestC.create(self);
  httpreq.headers.add('Accept: application/json; charset=utf-8');
  //httpreq.headers.add('X-Api-Key:'+aAPIkey);
  httpreq.useragent:= USERAGENT5;
  httpreq.SecurityOptions:= [soSsl3, soPct, soIgnoreCertCNInvalid];
  try
    if httpreq.get(Format(AURL,[aloc])) then begin
       httpres:= (httpreq.Response.ContentAsUTF8String)
       if verbose then writ('debug back '+formatJson(httpres));
       jsn:= TMcJsonItem.Create;
       jsn.AsJSON:= httpres;
       result.lat:= jsn.at(0,'lat').asnumber;
       result.long:= jsn.at(0,'lon').asnumber;
       result.descript:= Format('Coords: lat %2.5f lng %2.5f %s osm_id: %s ',
                                [result.lat,result.long,jsn.at(0,'name').asstring,
                                                        jsn.at(0,'osm_id').asstring]); 
    end else Writeln('APIError '+inttostr(Httpreq.Response.StatusCode2));
  except 
    writeln('EWI_APIHTTP: '+ExceptiontoString(exceptiontype,exceptionparam));  
  finally 
    writeln('Status3: '+gethttpcod(httpreq.Response.statuscode2))
    httpreq.Free;  
    sleep(200);
    jsn.Free;
  end; 
end;
Album Pascal
On page 10 published Geocoding Distance
Amsterdam – View from National Library (Biblio)
Tests with Python 3.13.3

Release Notes maXbox 5.2.7.120 May 2025 mX527 beta64-bit🐞


Add 21 Units (of 3771) + 15 Tutorials

  • py2,py3,py4,py5 (python3) enhanced template in bds_delphi.dci
  • now 142 Tutorials last: Geocode Distance maxbox_starter142.pdf
  • dmath64.dll renew functions data science package
  • maxbox_starter_testsequence51.bat added
  • new examples on https://sourceforge.net/projects/maxbox5/files/
  • ESC song available: examples/Sternenhaufen_Max_SunoAI.mp3
  • Issue BPM 123/124 has been released May 2025
  • source compatible with previous Version (see below)
  • update compatible for Python3.13 and Python3.14 use

15.05.2025 12:08
Release Notes maXbox 5.2.7.120 May 2025
SHA1: 5.2.7.120 maXbox5.exe e4568ca730781118bb5c16860c5872990ca35175
SHA1: ZIP file maxbox52.zip 1A89639AF491F6CF2AFE661C4E08EECDEDF95A7B

Learn Coding from the Scratch
maXbox 5.2.7.120 May 2025 mX527 beta64-bit🐞

Here’s a multi pascal program which displays potential log sawing patterns for band milling.

https://sourceforge.net/projects/maxbox5/files/examples/1335_logsaw_pattern13_64.txt/download

Go

If you are  not familiar with the game just do a web search on “Go game rules” or “Go game tutorial” and you’ll find plenty of sites. 

LE Models
ACME Models

Station2Station

Use this tool as a script (1274_GoogleDirForm2GeocodeDirectionsGeneral2request62.pas) to get the directions between any point using google maps. Enter a city or an address in both the From and the To address inputs. You can also set direct an lat- and longitude. Click Got to Google… (Find Directions), and the tool will display the route you need to take to get from your starting location to your end location in the browser. The turn by turn directions will be displayed below the map, and will contain the distance and approximate time it will take to get from one location to the other.

The GoogleDirForm from to box with geocoding and from open street maps.

The licence is a “licence”: “Data © OpenStreetMap contributors, ODbL 1.0. http:\/\/osm.org\/copyright”, and you can also get your own API-key. The a browser starts with the google maps directions window, as we checked the “Check To See Link In Browser”:

Berlin – Leipzig as Station to Station

Get or find coordinates: Search for a place using its latitude and longitude coordinates, or get the coordinates of a place you’ve already found.

Code behind

TDirection is working as a URL Builder: IsNavUtils – Provides a RNavigateLongLat record as class to manipulate Longitude and Latitude references and the functions and constants required to achieve this.
procedure TDirectionsBtnGoGoogleClick(Sender: TObject);
Var
  LocFrom,LocTo:RNavigateLongLat;
  Long,Lat:Double;
begin
  LocFrom:=RNavigateLongLat.create;
  Locto:=RNavigateLongLat.create;
  Long:=RealFrmDegreeText(EdtLong.Text);
  Lat:= RealFrmDegreeText(EdtLat.Text);
  LocFrom.CreateDec(Long,Lat);
  Long:=RealFrmDegreeText(EdtLong2.Text);
  Lat:= RealFrmDegreeText(EdtLat2.Text);
  LocTo.CreateDec(Long,Lat);
  // { 0 Start 1 End 3 Center }
  EdtGoogleLink.Text:=LocFrom.GoogleLinkDirectionsTo(LocTo, 0);
  LBlCrowFlies.Caption:='Distance as Crow Flys ='+FormatFloat('0.0km',LocTo.MetresFrom(LocFrom)/1000);
  if CBxGoNow.Checked then
     LocFrom.GoGoogleDirectionsTo(LocTo, 0);
end;

For the geocoding we use a restclient THttpRequestC a JSON Lib and the OSM API from nominatim. Nominatim uses OpenStreetMap data to find locations on Earth by name and address (geocoding). It can also do the reverse, find an address for any location on the planet. For occasional use. Use the API. Usage policy. API documentation. For power users. Install your own. The latest release is 4.5.0.

function TAddressGeoCodeOSM8(AURL, location, aApikey: string): tlatlong;
var Httpreq: THttpRequestC; httpres: string;
    Body: TMultipartFormBody;
    jsn: TMcJsonItem;
begin
  httpreq:= THttpRequestC.create(self);
  httpreq.headers.add('Accept: application/json; charset=utf-8');
  httpreq.useragent:= USERAGENT4;
  httpreq.SecurityOptions:= [soSsl3, soPct, soIgnoreCertCNInvalid];
  try
    if httpreq.get(Format(AURL,[location])) then begin
       //httpres:= (httpreq.Response.ContentAsString)
       httpres:= (httpreq.Response.ContentAsUTF8String)
       //writeln('conttype '+httpreq.Response.ContentType);
       writ('debug back '+formatJson(httpres));
       jsn:= TMcJsonItem.Create;
       jsn.AsJSON:= httpres;
       result.lat:= jsn.at(0,'lat').asnumber;
       result.long:= jsn.at(0,'lon').asnumber;
       result.descript:= Format('Coords: lat %2.5f  lng %2.5f %s place_id: %d',
                                [result.lat,result.long,jsn.at(0,'display_name').asstring,
                                                        jsn.at(0,'place_id').asinteger]); 
    end else Writeln('APIError '+inttostr(Httpreq.Response.StatusCode2));
    //StrReplace(httpres, '[{', '{');
  finally 
    writeln('Status3: '+gethttpcod(httpreq.Response.statuscode2))
    httpreq.Free;  
    sleep(200)
    jsn.Free;
  end; 
end;
Result: OSM _from: Coords: lat 46.94724 lng 7.45158 Münster, 1, Münsterplatz, Altstadt, Grünes Quartier, Stadtteil I, Bern, Verwaltungskreis Bern-Mittelland, Verwaltungsregion Bern-Mittelland, Bern/Berne, 3000, Schweiz/Suisse/Svizzera/Svizra place_id: 78089330
OSM _to: Coords: lat 51.33933 lng 12.37260 Thomaskirche, 18, Thomaskirchhof, Zentrum, Mitte, Leipzig, Sachsen, 04109, Deutschland place_id: 118838745
get geocoords: lat: 51.3393 - lon: 12.3726
mX5🐞 executed: 26/09/2024 09:52:14 Runtime: 0:0:4.38 Memload: 62% use

The GoogleDirForm is simple and a really simple form to put in Long/Lat references and also Locations and then get Google Directions in Browser:

Get Response Header Data and JSON Path Selection

HTTP headers are additional pieces of information sent along with an HTTP request or response. They provide important metadata about the request or response, such as the content type, caching directives, authentication credentials, and more.

These headers are sent by the server in response to a client’s request and provide information about the server or the response itself. Some commonly used response headers include:

  • Content-Type: Specifies the media type of the response body.
  • Cache-Control: Controls caching behavior for the response.
  • Set-Cookie: Sets a cookie in the client’s browser for maintaining the session state.
  • Location: Used in redirection to specify the new location for the requested resource.
  • RateLimit: httpq.GetResponseHeader(‘x-ratelimit-requests-remaining‘):

With THttpRequestC you can find a response header with hreq.Response.headers.values[‘server’]); and with TMcJsonItem you can parse JSON arrays of objects or get the json-path with jsn.path(‘data/name/store’).asstring:

function getEnergyStreamJSON4(AURL, feedstream, aApikey: string): string;
   var Hreq: THttpRequestC; httpres, encodURL: string;
       Body: TMultipartFormBody;
       jsn, jsno: TMcJsonItem;
       asp: TStringArray;
       rcnt: integer;
   begin
     hreq:= THttpRequestC.create(self);
     hreq.headers.add('Accept: application/json; charset=utf-8');
     hreq.headers.add('x-key:'+aAPIkey);
     hreq.useragent:= USERAGENTE;
     hreq.SecurityOptions:= [soSsl3, soPct, soIgnoreCertCNInvalid];
     try
       asp:= splitStr(feedstream,',');
       encodURL:= Format(AURL,[HTTPEncode(asp[0]),(asp[1]),asp[2]]);
       writeln(encodurl)      
       if hreq.get(encodURL) then begin
          httpres:= (hreq.Response.ContentAsUTF8String)
          writ('contenttype: '+hreq.Response.contenttype);
          rcnt:= hreq.Response.headers.count;
          writ('server: '+hreq.Response.headers.values['server']);
          for it:= 0 to rcnt-1 do 
             writ('resp_head: '+itoa(it)+' '+hreq.Response.headers[it]);
          //writ('debug back '+formatJson(httpres));
          jsn:= TMcJsonItem.Create;
          jsn.AsJSON:= httpres;
          result:= httpres;
          //writ(jsn.path('data/name').asstring);
          writ(jsn.values['dataset'].asstring);
          writ(jsn.values['data'].items[1]['code'].asstring);
          writ(jsn.values['data'].items[1]['gasInStorage'].asstring);
          jsno:= jsn.values['data'].items[1].asobject;
          writ(jsno['gasInStorage'].asstring);
         
          result:= Format('AGSI: store: %2.3f cons: %2.3f status:%s trend: %2.2f',
                             [jsno['gasInStorage'].asnumber,jsno['consumption'].asnumber,
                              jsno['status'].asstring,  jsno['trend'].asnumber]);  //}
       end else Writeln('APIError '+inttostr(Hreq.Response.StatusCode2));
     finally
       writeln('Status4: '+gethttpcod(hreq.Response.statuscode2))
       hreq.Free;  
       sleep(200)
       jsn.Free;
     end; 
   end; 

A major learning curve was how the user interface needs to be adapted for the very small screens and make it scriptable at runtime with maXbox5. I chose a Multi Layer Tab control template “Tabbed with Navigation” offered with Tokyo as a basis for my trail app. I had to add the functionality to support the hardware back button and was not very successful with gesture use opting in the end for Forward and Back Speed buttons so more to learn there. The Templates were for the time being not offered with my Rio and Alexandria Community Install.

Another point is to integrate the EdgeView browser with the RAD Studio 10.4 Sydney brings support for working with web content through the Chromium-based Edge WebView2 browser control in VCL applications via the new TEdgeBrowser component.

TEdgeBrowser supersedes TWebBrowser, which uses the Internet Explorer WebBrowser browser control. However TWebBrowser remains in the VCL component set, with some notable changes.

Delphi form as a browser plugin with a forthcoming web assembly

The script you can find at: https://sourceforge.net/projects/maxbox/files/Examples/EKON/EKON28/1274_GoogleDirForm2GeocodeDirectionsGeneral2request62.pas/download

station2station tracker test VII
station2station tracker test IX
station2station tracker test X
EKON 28 will be xenomorph

Trefft mich auf der EKON 28! In meiner Session zeige ich, wie du mit Google Directions API und Google Maps Wegbeschreibungen und Routen für verschiedene Transportmittel berechnest und visualisierst. Ich erstelle ein Navigation Advisor Projekt und demonstriere Geocoding sowie die Verwaltung von Diensten und Karten mit APIs und SDKs. Nutze den Rabattcode MaKl_EKON_28 und erhalte 15 % Ermäßigung auf die Tickets.

Pydemo67
Interrail in the meantime
Re 4/4 I-IV Track N (Lemaco, Fleischmann, Hobbytrain)

Summary

  • The Station2Station tool is a script (1274_GoogleDirForm2GeocodeDirectionsGeneral2request62.pas) that uses Google Maps to get directions between any two points.
  • Users can enter a city or address in the From and To address inputs, or set direct latitude and longitude coordinates. The tool displays the route in the browser, along with turn-by-turn directions, distance, and approximate time it will take to get from one location to the other.
  • The GoogleDirForm uses geocoding and Open Street Maps, with a license from OpenStreetMap contributors under ODbL 1.0. Users can get their own API-key for the tool.
  • The code behind the tool uses TDirection as a URL Builder, with RNavigateLongLat record as a class to manipulate longitude and latitude references. The tool uses a rest client, THttpRequestC, a JSON Lib, and the OSM API from Nominatim for geocoding.
  • Nominatim uses OpenStreetMap data to find locations on Earth by name and address, and can also do reverse geocoding.
  • The tool has been tested on Android Delphi 10.4 Sydney Targets API Level Android 29 (Android 10).
  • The tool’s author will be presenting a session at EKON 28, demonstrating how to use Google Directions API and Google Maps to calculate and visualize routes for different modes of transportation. A discount code, MaKl_EKON_28, is available for 15% off tickets to EKON 28.

2Rex

In the following section we can see the integration of weather- or geocode data in our app station2station. We use an API and a RegEx:

Const
  UrlWeatherReport25=
     'https://api.openweathermap.org/data/2.5/weather?q=%s&units=metric&APPID'+
                          '=55013bf3d09cfb0619989a00ed5bed_____yourAPIKey';
  GEOCoordREX3 = 
              '"lon":([\d\.-]+).*"lat":([\d\.-]+).*"temp":([\d\.-]+).*'; 

Better solution is to get the API from an include file with a const called OWMKEY:

{$I owmapikey.inc }
Const
  UrlWeatherReport25=
     'https://api.openweathermap.org/data/2.5/weather?q=%s&units=metric&APPID'+                                   
                                       OWMKEY;

Next we call the API with a simple HTTPGet() to return the JSON String Stream:

function GetGeoWeather(const location: string;
                                  const UrlRestAPI: string): string;
 var lStrm: TStringStream;
begin
  lStrm:= TStringStream.Create('');
  try
     try
       HTTPGet(Format(UrlRestAPI,[location]),lStrm);
     except
        //if something wrong try using a backup server.
        //writeln('htmlback: '+GetURLAsString('http://api.openweathermap.org'));
       writeln('OWeather_Map Exception: '+Gethtm(UrlWeatherReport25))
     end;
     lStrm.Seek(0,0);
     result:= +(lStrm.ReadString(lStrm.Size));
  finally
     lStrm.Free;
  end;
end;

With the https result we parse the Utf8 JSON with a RegEx:

function GEOCoord2PointX2(apistr: string): TFloatPoint;
 begin
   setdecimalseparator('.')
   with TRegEx.Create(GEOCoordREX3,[rroIgnoreCase]) do try 
     if match(apistr).success then begin
       result.x:= strtofloat(match(apistr).groups[1].value)
       result.y:= strtofloat(match(apistr).groups[2].value)
       temp:= strtofloat(match(apistr).groups[3].value)
     end;     
    finally Free; 
   end;
 end; 

In the end we do have separation of concern in call the API, parse the result and show the data on console or as a return function ShowGeoWeather(): string for further format:

 procedure ShowGeoWeather;
 begin
   //sr:= GetGeoWeather(removespaces('Melbourne,AU'),UrlWeatherReport25);
   sr:= GetGeoWeather(removespaces('Bern, CH'),UrlWeatherReport25);
   writeln(formatjson(sr))
   // writeln('GEO_Weather_Report5: '+sr);
   lonf:= GEOCoord2PointX2(sr).x  
   latf:= GEOCoord2PointX2(sr).y 
   PrintF('Lon: %.4f - Lat: %.4f ',[lonf, latf]) 
   writ('geoweather coords: '+format('Lon: %.4f -Lat: %.4f -temp:%.2f°',
                                                     [lonf,latf,temp])); 
 end;

Beginner RegEx question. I have lines of JSON in a textfile, each with slightly different Fields like coords or weather array, but there are 3 fields I want to extract for each object line if it has it, ignoring everything else. How would I use a regex (in editpad, script, shell or anywhere else) to do this?

Don’t try to parse JSON yourself. This is a solved problem. People have already written, tested and debugged code that handles this already. You can use a JSON Parser or a RegEx Group!

This next with a JSON Parser:

function GEOCoord2PointX3(apistr: string): TFloatPoint;
   begin
     setdecimalseparator('.')
     with TMcJsonItem.Create do begin
       AsJSON:= apistr;
       result.x:= at(0,'lat').asnumber;
       result.y:= at(0,'lon').asnumber;
       temp:= at(3,'temp').asnumber;
       sunrise:= path('sys/sunrise').asinteger;  //index independent!
       sunset:= path('sys/sunset').asinteger;
       free;
     end;
   end; 

Get a key-value JSON with a Regular Expression, the following regex expression extract exactly the “fid” field value “321”:

regs:= '{"fid":"321","otherAttribute":"value"} ';
writeln(formatjson(regs))
writ(regexFindall(regs, '(?<=\"fid\":\")[^\"]*'));
{
    "coord": {
        "lon": 7.4474,
        "lat": 46.9481
    },
    "weather": [
        {
            "id": 500,
            "main": "Rain",
            "description": "light rain",
            "icon": "10n"
        }
    ],
    "base": "stations",
    "main": {
        "temp": 11.03,
        "feels_like": 10.33,
        "temp_min": 10.27,
        "temp_max": 12.74,
        "pressure": 1011,
        "humidity": 82,
        "sea_level": 1011,
        "grnd_level": 939
    },
    "visibility": 10000,
    "wind": {
        "speed": 0.81,
        "deg": 142,
        "gust": 0.47
    },
    "rain": {
        "1h": 0.52
    },
    "clouds": {
        "all": 60
    },
    "dt": 1728239017,
    "sys": {
        "type": 2,
        "id": 2012960,
        "country": "CH",
        "sunrise": 1728192953,
        "sunset": 1728234020
    },
    "timezone": 7200,
    "id": 2661552,
    "name": "Bern",
    "cod": 200
}
JSON Parser Online

"dt": 1728209107,
"sys": {
"type": 1,
"id": 6937,
"country": "CH",
"sunrise": 1728192953,
"sunset": 1728234020
},
"timezone": 7200,
"id": 2661552,
"name": "Bern",
"cod": 200
}
Lon: 7.4474 - Lat: 46.9481
geoweather coords: Lon: 7.4474 - Lat: 46.9481 -temp:9.01°
mX5🐞 executed: 06/10/2024 12:08:21 Runtime: 0:0:3.244 Memload: 59% use

JSON Parser as RegEx

This regular expression finds a key-value pair in JSON formatted strings

For those who want to see that a TMachCollection are matches of groups I found a stackoverflow testdocument in which we convert the RegEx in a TMatchCollection:

const TESTJSON =
'[                                              '+LF+
'  {                                            '+LF+
'    "_id": "56af331efbeca6240c61b2ca",         '+LF+
'    "index": 120000,                           '+LF+
'    "guid": "bedb2018-c017-429E-b520-696ea3666692", '+LF+
'    "isActive": false,                              '+LF+
'    "balance": "$2,202,350",                        '+LF+
'    "object": {                                     '+LF+
'        "name": "amx",                         '+LF+
'        "lastname": "lang"                     '+LF+
'    }                                          '+LF+
'  }                                            '+LF+
']                                              ';

writ(regexFindall(TESTJSON, 
   '(?:\"|\'')(?<key>[^"]*)(?:\"|\'')(?=:)(?:\:\s*)(?:\"|\'')?(?<value>true|false|[0-9a-zA-Z\+\-\,\.\$]*)'));  

>>> 8 Matches [ ]:
[ "_id": "56af331efbeca6240c61b2ca ][ "index": 120000, ]
[ "guid": "bedb2018-c017-429E-b520-696ea3666692 ]
[ "isActive": false ][ "balance": "$2,202,350 ][ "object":  ]
[ "name": "am ][ "lastname": "lang ]

with TRegEx.Create(sr,[rroIgnoreCase]) do try 
   mats:= Matches(TESTJSON);
   //for group in matches do
   for m:= 0 to mats.count-1 do begin
     for g:= 1 to mats[it].groups.count-1 do
       writ(format('matchgrp[%d,%d]: %s ',[m,g,mats[m].groups[g].value]));
   end; 
  writ('match group[direct] balance: '+mats[4].groups[2].value);      
 finally Free; 
end;    

>>> 8 matches each 3 groups
matchgrp[0,1]: _id 
matchgrp[0,2]: 56af331efbeca6240c61b2ca 
matchgrp[1,1]: index 
matchgrp[1,2]: 120000, 
matchgrp[2,1]: guid 
matchgrp[2,2]: bedb2018-c017-429E-b520-696ea3666692 
matchgrp[3,1]: isActive 
matchgrp[3,2]: false 
matchgrp[4,1]: balance 
matchgrp[4,2]: $2,202,350 
matchgrp[5,1]: object 
matchgrp[5,2]:  
matchgrp[6,1]: name 
matchgrp[6,2]: amx 
matchgrp[7,1]: lastname 
matchgrp[7,2]: lang 
match group[direct] balance: $2,202,350
mX5 executed: 06/10/2024 16:49:24  Runtime: 0:0:3.482  Memload: 57% use 
https://regex101.com/r/zR2vU9/4
Märklin 3067.5, from ‘1975 to ‘1976, body Roed/Black DSB inscription fine
py modul package sympy
Goldbachs Comet
4 Nations: Märklin DB E10 1266 – B 1606 – TAB SNCF CC 6544 – Piko SBB Re 4/4 1034 TEE Classic

Der kosmopolitische Stadtteil Pempelfort ist für seine kulturellen Einrichtungen am Rhein bekannt.

Happy New Year 2025

Compare OWM Python – Pascal

Get real-time weather updates every hour and never forget your umbrella again:

Const PyWeather =  
  'def get_weather():                    '+LF+
  '   url = f"http://api.openweathermap.org/data/2.5/weather?q={CITY}&appid={API_KEY}"'+LF+
  '   response = requests.get(url)       '+LF+
  '   data = response.json()             '+LF+
  '   return data[''weather''][0][''description''], data[''main''][''temp'']-273.15';


procedure Weather_PySolution(loc: string);
var OWMKEYS: string;
begin
 with TPythonEngine.Create(Nil) do begin
   loaddll;   //pythonhome:= PYHOME64;
   autofinalize:= false;
   try
      Execstring('import re, requests, time');
      OWMKEYS:= ''''+ReplaceStr(OWMKEYPY,'''','''''')+'''';
      writeln('apikey:'+ OWMKEYS);
      Execstring('API_KEY = '+OWMKEYS+'; CITY = '+loc);
      Execstring(PyWeather);
      Execstr('weather, temp = get_weather()');
      println(evalstr('(f"Current weather in {CITY}: {weather}, {temp:.2f} C.")'));    
   except
      raiseError;
   finally
      UnloadDll;
      Free;
   end;
 end; 
end;  

And in pure Python:

import requests
import time

API_KEY = 'your_api_key'
CITY = 'Basel,CH'

def get_weather():
    url = f"http://api.openweathermap.org/data/2.5/weather?q={CITY}&appid={API_KEY}"
    response = requests.get(url)
    data = response.json()
    return data['weather'][0]['description'], data['main']['temp'] - 273.15

while True:
    weather, temp = get_weather()
    print(f"Current weather in {CITY}: {weather}, {temp:.2f}°C")
    time.sleep(3600)  # Run every hour
const DEF_SPEECH =
   'def text_to_speech(text):   '+LF+
   ' engine = pyttsx3.init()    '+LF+
   ' engine.say(text)           '+LF+
   ' engine.runAndWait()        ';

Voice in Python

You has to install C:\maxbox\maxbox4\maxbox4>py -3.12 -m pip install pyttsx3

Then I have had this error when trying to create a python service using pywin32 module. 
I copied pythoncom38.dll and pywintypes38.dll into the root directory of the project and it solved the issue. (Exception: ModuleNotFoundError: No module named ‘pywintypes’ at 868.1496)

For me it worked to copy the files (pythoncom38.dll and pywintypes38.dll) from: C:\Users\”Your user id”\AppData\Roaming\Python\Python38\site-packages\pywin32_system32 to the path: C:\Users\”Your user id”\AppData\Roaming\Python\Python38\site-packages\win32\lib

procedure Weather_PySolution(loc: string);
var OWMKEYS: string;
begin
 with TPythonEngine.Create(Nil) do begin
   //pythonhome:= PYHOME64;
   loaddll;
   autofinalize:= false;
   try
      Execstring('import re, requests, time, pyttsx3');
      println('Py_Weather_algorithm#Functional _requests strip-split-slice: ');
      OWMKEYS:= ''''+ReplaceStr(OWMKEYPY,'''','''''')+'''';
      writeln('apikey:'+ OWMKEYS);
      Execstring('API_KEY = '+OWMKEYS+'; CITY = '+loc);
      Execstring(PyWeather);
      Execstring(DEF_SPEECH);
      Execstr('weather, temp = get_weather()');
      println(evalstr('(f"Current weather in {CITY}: {weather}, {temp:.2f} C.")'));  
      Execstr('text_to_speech('''+evalstr('(f"Current weather in {CITY}:{weather},{temp:.2f} C.")')+''')'); 
   except
      raiseError;
   finally
      UnloadDll;
      Free;
   end;
 end; 
end;  

The interesting line is the combination of execstr() and evalstr() cause we want to make the result audible (nous voulons rendre le résultat audible).

 {To get the current weather data of any city using the OpenWeatherMap 
     API in Python, you can use the requests and json modules. Here is an example: 

 ‘data = requests.get(f”https://api.openweathermap.org/data/2.5/weather?q={city}&units=metric&appid={api_key}”).json()’+LF+ ‘print(f”Weather in {city}: {data[”weather”][0][”description”]}”) ‘+LF+ ‘print(f”Temperature (in celcius) = {data[”main”][”temp”]}”)’);  
      
The OpenWeatherMap API is a service that provides weather data, including current weather data, forecasts,  and historical data. It offers an API with JSON, XML, and HTML endpoints, and a limited free usage tier. 
     To use the API, you need to create an account on openweathermap.org and obtain an API key.}

5 Nations Locs
BR E 10 Tracks
BPM #120 with a post API image pipeline from station2station
SNCF, locomotive électrique CC 6526 « Le Capitole », ép. IV – coffret anniversaire
SNCF, locomotive électrique CC 6526 « Le Capitole », ép. IV –
Re 4/4 II Märklin Z 11161, Fleischmann N 11251, Roco H0 11160, Hermann 0 11161

Linear Regression Fit

Linear regression is widely used in business to model relationships between variables. It helps predict outcomes based on input data.

execstr('from sklearn.linear_model import LinearRegression');
execstr('# Data: Months and Sales (in thousands of dollars)       '+LF+
       'months = np.array([1, 2, 3, 4, 5]).reshape(-1, 1)           '+LF+
       'sales = np.array([10, 12, 15, 20, 22])  # Sales in $1000s   '+LF+
       '                                                            '+LF+
       '# Create a linear regression model                          '+LF+
       'model = LinearRegression()                                  '+LF+
       '                                                            '+LF+
       '# Fit the model to our data                                 '+LF+ 
       'model.fit(months, sales)                                    '+LF+
       '# Predict sales for the 6th month                           '+LF+
       'predicted_sales = model.predict([[6]])                      ');  
     
execstr('print(f"Predicted Sales for month 6: ${predicted_sales[0]:.2f}k")'); 

We’ll use linear regression to predict future sales based on the previous month’s data.

The model predicts sales of $24,400 for month 6 based on historical sales data. Linear regression is an essential tool in sales forecasting, helping businesses plan inventory and marketing campaigns.

from sklearn.linear_model import LinearRegression
import numpy as np

# Data: Months and Sales (in thousands of dollars)
months = np.array([1, 2, 3, 4, 5]).reshape(-1, 1)
sales = np.array([10, 12, 15, 20, 22])  # Sales in $1000s

# Create a linear regression model
model = LinearRegression()

# Fit the model to our data
model.fit(months, sales)

# Predict sales for the 6th month
predicted_sales = model.predict([[6]])
print(f"Predicted Sales for month 6: ${predicted_sales[0]:.2f}k")
La Gomera Jardin Tecina
FM SNCF 68006, Jouef CC 6542, Trix CC 40105, Märklin BB 22347 – @TfrmMtxPlot
Rheingold Set
One Month Test 8.1.-5.2. 2025 (8 + 4*7=36)-31= 5.
From Lichfield to Geneva

EKON 28

More than 25 Speakers and over 30 Sessions with interaction and support: Profit from family conferences EKON 28 and learning, innovation and development in individual projects.

4. – 6. November | Düsseldorf

Use modern RegEx

When you start building scripts and apps, you are often faced with almost the same problems. Instead of laboriously constructing loops and queries, we look at the use of modern RegEx in Delphi and Python. Modern refers to 64-bit and Unicode, and pattern matching and stemming are also in demand in AI development or the Human Genome Project. Google, for example, probably uses an analogous process for organic search. Tips and tricks from the PCRE round off the express.

PCRE RegEx

System.RegularExpressionsCore

Packagertl270.bpl

Classes

ERegularExpressionError
TPerlRegExDelphi wrapper around the open source PCRE library.
TPerlRegExListA list of TPerlRegEx instances.
RegularExpression as Client uses Core (uses System.SysUtils, System.RegularExpressionsCore;)
envlist:= Tstringlist.create;
   InStr:= loadfile(Exepath+'\restcountrieskeysutf812.txt');
   writ(formatJSON(utf8decode(instr)));
   //getJsonData2(utf8decode(instr),'translations','common');
   //jSplit( const Delimiter : char; Input :Str; Strings : TStrings);
   jSplit( '}', utf8decode(instr), envlist);
   //StrtoList(InStr, envlist, CRLF)
   writeln('envlist count: '+itoa(envlist.count));
   cnt:= 0;
   regEx:= TRegEx.create('common":"[\w]',[rroNotEmpty]); 
   //regEx.regex:='common [\w+:\w:\w :,]+ Sui';
   // Execute search ot TMatch
   for it:= 0 to envlist.count-1 do 
     if regEx.match((envlist[it])).success then begin
        writeln(itoa(cnt)+':'+envlist[it]);
        inc(cnt)
     end;  
   regex.Free;
   envlist.Free;    //*)
   
langitem: 19	Švajčiarska konfederácia, slk
langitem: 20 Confederación Suiza, spa
langitem: 21 Швајцарска Конфедерација, srp
langitem: 22 Schweiziska edsförbundet, swe
langitem: 23 İsviçre Konfederasyonu, tur
langitem: 24 سوئیس متحدہ, urd
langitem: 25 瑞士联邦, zho
N:= TMcJsonItem.Create;
  N.AsJSON := savestr;
  for it:= 0 to N['name']['translations'].count-1 do begin
    //writ('enumerator count '+itoa(N['name'].count-1));
    item:= N['name']['translations'].items[it];
    write(item.S['official']+' ')
  end; 
NLTK (Natural Language Toolkit) uses Regex package

Regex in Python

procedure PyCodeREgEx(tex: string);
begin
  with TPythonEngine.Create(Nil) do begin
  try
    loadDLL;
    //autofinalize:= false;
    ExecString('import re, json');
    execstr('txt = "The rain in Explain"');
    //if it starts with "The" and ends with "plain":
    Println('regex test: '+EvalStr('re.search("^The.*plain$", txt)')); 
    execstr('x = re.search("^The.*plain$", txt)');
    Println('regex test: '+EvalStr('type(x)')); 
    Println('regex test: '+EvalStr('bool(x)')); 
   // Println(EvalStr('decode_and_print_json('+JSONDATA+')'));
  except
    raiseError;        
  finally 
    unloadDLL;      
    free;
  end; 
 end;
end; 

regex test: <re.Match object; span=(0, 19), match='The rain in Explain'>
regex test: <class 're.Match'>
regex test: True
TMatchEvaluator Problem closed
ask the ai
procedure RegexExamplePerplex2;
//uses  //SysUtils, RegExpr;
var matchr: TMatch;
begin
  with TRegEx.Create1('\d{3}') do   // pattern to match three digits
  try
    matchr:= Match('abc 123 def 456') ;
     repeat
       WriteLn('Found match: '+matchr.value);
       matchr:= matchr.NextMatch; 
     until not matchr.success 
  finally
    Free;
  end;
end;

Integrate Google Maps API.

The Google Directions API and Maps (Earth) are two powerful tools that can be used to calculate and visualize directions and routing between locations using various modes of transportation. The Google Maps Platform is also demonstrated with geocoding, I create a Trip Advisor project to then manage services, credentials, calculations, maps, coordinates in APIs and SDKs.

Google Directions
map editor with resource editor
Geo Coding with URL_APILAY_GEO = ‘https://api.apilayer.com/geo/country/capital/%s&#8217;;  
function TAddressGeoCodeOSM8(AURL, location, aApikey: string): tlatlong;
var Httpreq: THttpRequestC; httpres: string;
    Body: TMultipartFormBody;  jsn: TMcJsonItem;
begin
  httpreq:= THttpRequestC.create(self);
  httpreq.headers.add('Accept: application/json; charset=utf-8');
  httpreq.useragent:= USERAGENT5;
  httpreq.SecurityOptions:= [soSsl3, soPct, soIgnoreCertCNInvalid];
  try
   if httpreq.get(Format(AURL,[location])) then begin
     httpres:= (httpreq.Response.ContentAsString)
     writ('debug back '+FormatJson(httpres));
     jsn:= TMcJsonItem.Create;
     jsn.AsJSON:= httpres;
     result.lat:= jsn.at(0,'lat').asnumber;
     result.long:= jsn.at(0,'lon').asnumber;
     result.descript:= Format('Coords: lat %2.5f  lng %2.5f %s place_id: %d',
                         [result.lat,result.long,jsn.at(0,'display_name').asstring,
                                         jsn.at(0,'place_id').asinteger]); 
    end else Writeln('APIError '+inttostr(Httpreq.Response.StatusCode2));
    //StrReplace(httpres, '[{', '{');
  finally  
    writeln('Status3: '+gethttpcod(httpreq.Response.statuscode2))
    httpreq.Free;  
    sleep(200)
    jsn.Free;
  end; 
end;

McJson use a Simple Object-Pascal native code using TList as internal data structure with a Single-pass string parser and is just one unit (McJSON) and just one class(TMcJsonItem) integrated in maXbox.

Status3: SC_OK
debug back [{
"place_id": 56362293, "licence": "Data B) OpenStreetMap contributors, ODbL 1.0. http:\/\/osm.org\/copyright", "osm_type": "relation", "osm_id": 1676328,
"lat": "46.5576439", "lon": "15.6455854",
"class": "boundary", "type": "administrative",
"place_rank": 16, "importance": 0.5929484692666679,
"addresstype": "municipality",
"name": "Maribor", "display_name": "Maribor, Slovenija",
"boundingbox": ["46.4994068","46.6342916","15.5169925","15.7722677"
]
}
]
Status3: SC_OK

RAD Studio 10.4 Sydney brings support for working with web content through the Chromium-based Edge WebView2 browser control in VCL applications via the new TEdgeBrowser component.

TEdgeBrowser requires access to WebView2Loader.dll for it to work. I’m guessing this is what you might be missing in older project. 

Geo Tracking Solution

Geo Tracking Post Logistic Test III
Geo Tracking Post Logistic Test IV
 loadFMXForm();
 
  //function TAddressGeoCodeOSM5 is now internal precompiled  > V51470
  //latlong:=  TAddressGeoCodeOSM5('Hauptbahnhof, Graz, Austria');
 
  writeln('OSM _from: '+f_latlong.descript);
  writeln('OSM _to:   '+t_latlong.descript);
  writeln('get geocoords: '+format(' lat: %.4f - lon: %.4f',[t_latlong.lat,t_latlong.long])); 
  coords.caption:= coords.caption+format(' Dest: lat: %.4f - lon: %.4f',[t_latlong.lat,t_latlong.long]); 
  OpenWeb('https://www.latlong.net/c/?lat='+flots(t_latlong.lat)+'&long='+flots(t_latlong.long));
  loadWebform();
  WebBrowser1.Navigate('https://wttr.in/Ljubljana');
Modern Weather Report Map

mX5.1.4.98 XII

The latitude 46.6320803 and longitude 14.144223381010908 shown on map. Picture: Max K.
GPS coordinates: 46° 37′ 55.4891” N 14° 8′ 39.2042” E

GPS coordinates: 46° 37′ 12.6595” N 14° 19′ 31.4436” E
Weather Report GPS coordinates: 46° 37′ 55.4891” N 14° 8′ 39.2042” E
OpenStreetMap Weather Report GPS coordinates: 46° 37′ 55.4891” N 14° 8′ 39.2042” E

Python 3.12.x 64-bit in maXbox5.1

Normally it shuts down after one run, so you have to set autofinalize:= false

with TPythonEngine.Create(Nil) do begin
   //pythonhome:= PYHOME64;  optional 
   //opendll(PYDLL64)
   loadDLL;
   autofinalize:= false;
   try
Matplotlib 3.9.0 as py -3.12 -m pip install -U matplotlib
Updated Pandas 2.2.2

Codemap in maXbox5

The extension functionality is straightforward. Just click the code map item code search <Ctrl F3> and it will trigger the navigation to the document where the corresponding code element / block is defined in the document and you can just load a new script by dblclick.

Unicode Codemap 5
Unicode Codemap 5 II
Lemaco CC 40110 Blason Nice
CC 40110 on stage
CC 40101 from RailPic
4 Nations Locs SNCF CC 6510 – SBB 10101 – DB E 10 158 – ÖBB 1042.10
Pink Floyd: This is the peak of music itself, it literally can´t go any higher than this
Last Picture I got with N. Wirth from 2023
EKON 28 2024
Breisach, July 2024
Elsass: S.A.C.M. Elsässische Maschinenbauanstalt Graffenstaden C-Kuppler (2x) – Baujahr 1900, Pic: Max
Wurmlingen /Tübingen 18.08.2024
V 218 Lokomotive 218 105-5 der Westfrankenbahn in Aschaffenburg und V 200 035

AsciiShape

The main difference between this implementation and others is the ability to specify colors of the shapes. After the shape you can define as much colors then the number of shapes in the picture.

https://sourceforge.net/projects/maxbox/files/Examples/13_General/1327_ascii_shape_imageMain_demo1.pas/download

An other difference with the original code is that the lines do not need to be all equals in lenght, the largest one define the final image width.

RAD Studio 12.1

Python & Pascal executed
EKON Samples from the Archive

Post API Image Pipeline

The Object Detection API provides fast and accurate image object recognition using advanced neural networks developed by machine learning experts and pretrained models.

First we send an input image by Post (PostMultipartFormDataStream), return a list of detected objects labels, confidence percentages and bounding boxes. Objects with confidence less than 0.3 (30%) are filtered out. The image we get with the first step of the pipeline:

function GEO_to_text_API2_randimage2(AURL, url_name, aApikey: string): string;
var httpq: THttpConnectionWinInet;
    rets: TMemoryStream;  
    heads: TStrings; iht: IHttpConnection; 
    Decoder: TIdDecoderMIME;
begin
  httpq:= THttpConnectionWinInet.Create(true); 
  rets:= TMemoryStream.create;
  heads:= TStringlist.create;     
  try 
    heads.add('X-Api-Key='+aAPIkey);
    heads.add('Accept=image/jpg');
    iht:= httpq.setHeaders(heads);
    httpq.Get(Format(AURL,[urlencode(url_name)]), rets);
    if httpq.getresponsecode=200 then begin
       rets.Position:= 0;
       //ALMimeBase64decodeStream(rets, rets2)
       rets.savetofile((exepath+'randimage0.jpg'));
       openfile(exepath+'randimage0.jpg');
     end  
      else result:='Failed:'+
             itoa(Httpq.getresponsecode)+Httpq.GetResponseHeader('message');
  except  
    writeln('EWI_HTTP: '+ExceptiontoString(exceptiontype,exceptionparam));
  finally
    httpq:= Nil;
    heads.Free;
    rets.Free;
  end;                  
end;                 //}

The Random Image API generates random images for all your placeholder and design needs. It Returns a random, base64-encoded image in JPEG format. Don’t forget to set the Accept Header otherwise you have to decode with ALMimeBase64decodeStream. The Accept (required) – header indicating the content type to accept in the result. Must be set to the following: image/jpg.

The Randimage we get

Second step is to post the image for object-detection.

https://api-ninjas.com/api/objectdetection

The image (required) – must be an input image file. Must be either JPEG or PNG format and smaller than 2000 by 2000. Also the X-Api-Key (required) – API Key associated with your account.

Procedure PyCodeObjectDetect(imgpath, aAPIKey: string);
begin
  with TPythonEngine.Create(Nil) do begin
  //pythonhome:= 'C:\Users\User\AppData\Local\Programs\Python\Python312\';
  try
    loadDLL;
    ExecString('import requests');
    ExecStr('url= "https://api.api-ninjas.com/v1/objectdetection"'); 
    ExecStr('image_file_descriptor = open("'+imgpath+'", "rb")');  
    ExecStr('headers= {"X-Api-Key": "'+aAPIKey+'"}'); 
    ExecStr('files = {"image": image_file_descriptor}  ');
    ExecStr('r=requests.post(url, headers=headers, files=files)');
    println(EvalStr('r.json()')); 
  except
    raiseError;        
  finally       
    free;
  end; 
 end;
end; 

Behind the is the complicated configuration of a multipartformdata mechanism. On the other hand, multipart/form-data is the encoding used when an HTML form has a file upload field. When you make a POST request, you have to encode the data that forms the body of the request in some way.

  • application/x-www-form-urlencoded is more or less the same as a query string on the end of the URL.
  • multipart/form-data is significantly more complicated but it allows entire files to be included in the data.
  • multipart/form-data: adds a few bytes of boundary overhead to the message, and must spend some time calculating it, but sends each byte in one byte.
Procedure PostMultipartFormData(const aUrl:AnsiString;
                                const aRequestFields: TALStrings;
                                const aRequestFiles: TALMultiPartFormDataContents;
                                const aResponseContent: TStream;
                                const aResponseHeader: TALHTTPResponseHeader2;
                                const ARequestHeaderValues: TALNameValueArray = nil); overload;

https://code-maze.com/aspnetcore-multipart-form-data-in-httpclient/      

Then we send the request and get the following JSON result of the detector (Sample Response):

[{‘label’: ‘boat‘, ‘confidence’: ‘0.52’, ‘bounding_box’: {‘x1’: ‘308’, ‘y1’: ‘179’, ‘x2’: ‘527’, ‘y2’: ‘328’}}, {‘label’: ‘umbrella’, ‘confidence’: ‘0.46’, ‘bounding_box’: {‘x1’: ‘308’, ‘y1’: ‘179’, ‘x2’: ‘527’, ‘y2’: ‘328’}}, {‘label’: ‘boat’, ‘confidence’: ‘0.34’, ‘bounding_box’: {‘x1’: ‘385’, ‘y1’: ‘277’, ‘x2’: ‘425’, ‘y2’: ‘295’}}, {‘label’: ‘bed’, ‘confidence’: ‘0.32’, ‘bounding_box’: {‘x1′: ’10’, ‘y1′: ’14’, ‘x2’: ‘630’, ‘y2’: ‘449’}}, {‘label’: ‘boat’, ‘confidence’: ‘0.31’, ‘bounding_box’: {‘x1’: ‘384’, ‘y1’: ‘285’, ‘x2’: ‘426’, ‘y2’: ‘298’}}, {‘label’: ‘cat’, ‘confidence’: ‘0.31’, ‘bounding_box’: {‘x1’: ‘9’, ‘y1′: ’15’, ‘x2’: ‘630’, ‘y2’: ‘449’}}, {‘label’: ‘person‘, ‘confidence’: ‘0.3’, ‘bounding_box’: {‘x1’: ‘8’, ‘y1′: ’11’, ‘x2’: ‘633’, ‘y2’: ‘444’}}]

Yes we can see the boat and the small person, the umbrella maybe a false positive of the cave. A cat or a bed could be an imagination. We also have a false negative, the unseen sea or sky. Also a live demo is available:

Live API Demo

You can use a late binding with an OleObject and OleVariants of :WinHttp.WinHttpRequest

https://api-ninjas.com/api/textsimilarity

function TextSimilarity_API6(AURL, url_name, aApikey: string): string;
var
  httpReq,hr: Olevariant;
  JPostdatabody: string;
  jo: TJSON;
begin
  Result:= '';
  JPostDataBody:= '{' +
    '"text_1": "gpt-3.5-turbo-instruct",'+
      //'"prompt": "%s",'+
    '"text_2": "gpt-3.5-turbo-instruct777"'+
    '}';

  // Use JSON for REST API calls and set API KEY via requestheader
  httpReq:= CreateOleObject('WinHttp.WinHttpRequest.5.1');
  jo:= TJSON.Create();
  try             
    hr:= httpReq.Open('POST', AURL, false);
    httpReq.setRequestheader('user-agent',SUSERAGENT);
    // Select HTTPS POST method, set POST data, specify endpoint URL
    httpReq.setRequestheader('content-type','application/json'); 
    httpReq.setRequestheader('X-Api-Key',aApikey);
    if hr= S_OK then HttpReq.Send(JPostDataBody);
    If HttpReq.Status = 200 Then
       result:= HttpReq.responseText
    Else result:= 'Failed getresponse:'+itoa(HttpReq.Status)+HttpReq.responseText;
      // writeln('debug response '+HttpReq.GetAllResponseHeaders); 
      // Process returned JSON when request was successful 
    jo.parse(result) 
    result:='Answer2similarity: '+jo.values['similarity'].asstring;
  finally
    jo.Free;
    httpreq:= unassigned;  
  end;                
end;

Answer2similarity: 0.911304295063019
True
mX5🐞 executed: 17/04/2024 20:40:42 Runtime: 0:0:3.895 Memload: 71% use
RemObjects Pascal Script. Copyright (c) 2004-2024 by RemObjects Software & maXbox5

BR V221 TEE Merkur, Rheingold
Liliput 1042
TEE Adriatico with TEE Le Rhodanien

AGSI Update

function getEnergyStreamJSON21(AURL, feedstream, aApikey: string): string;
var encodURL: string;
    httpRq,hr: Olevariant;
    asp: TStringArray;
begin
  httpRq:= CreateOleObject('WinHttp.WinHttpRequest.5.1');
  // Opens HTTPs connection.  
  try 
    asp:= splitStr(feedstream,',');
    encodURL:= Format(AURL,[HTTPEncode(asp[0]),(asp[1]),asp[2]]);   
    writeln(encodurl)        
    hr:= httpRq.Open('GET', encodURL, false);
    httpRq.setRequestheader('user-agent',USERAGENTE);
    httpRq.setRequestheader('x-key',aAPIkey); 
    if hr= S_OK then HttpRq.Send();
    If HttpRq.Status = 200 Then
       result:= HttpRq.responseText
    Else result:= 'Failed getting response:'+itoa(HttpRq.Status)+HttpRq.responseText;
        //writeln('debug response: '+HttpReq.GetAllResponseHeaders); 
  except  
    writeln('Error: '+HttpRq.responseText);
    writeln('EHTTP: '+ExceptiontoString(exceptiontype, exceptionparam));       
  finally
    httprq:= unassigned;
  end;                  
end; 
AGSI Update
HttpResponse:= getEnergyStreamJSON21(URL_AGSIAPI2,’DE,2024-03-15,200′,AGSI_APIKEY);
View3D := true;

The future of gas storage: green hydrogen

Gas storage could also play an important role in the energy system of the future. If we switch completely to renewable energies as part of the energy transition, balancing demand is absolutely necessary. This is because renewable energies such as wind and solar depend on the weather.

When wind conditions are favorable or when the sun shines often, more energy is generated than is currently needed. At other times, energy is needed even though none is currently being produced. The production and consumption of energy must therefore be decoupled in time in order to be able to cover energy needs at all times. However, electricity cannot currently be stored in large quantities and for long periods of time – the longer-term storage of hydrogen, on the other hand, is possible.

The excess green electricity from volatile wind and solar energy could be converted into green hydrogen in a power-to-gas (PtG) plant and fed into the gas storage facilities. At peak demand, when more energy is needed, the hydrogen from the gas storage facilities could be converted back into electricity and fed into the power grid.

A research project entitled “Storing hydrogen – that much is certain”, in which GASAG is also involved, has examined the gas storage facilities in Germany for their suitability for hydrogen storage. The result: all cavern storage facilities and four of the pore storage facilities in Germany are – after the necessary conversions – available for storing hydrogen. This would be another step towards the energy transition.

https://www.gasag.de/magazin/neudenken/wie-funktioniert-ein-gasspeicher

Geocoding II

maXbox Starter93 – Code with Geocoding

In the beginning there was nothing, which exploded. — Terry Pratchett

Geocoding is the processing of single addresses into geographic coordinates and can be performed by a number of free online web sites. Many of these same sites can also perform reverse geocoding, or the use of geographic coordinates to determine addresses or place names. The web site links below provide access to free single address or place name geocoding services. I want to show 2 of them, a commercial and a free one.

Just like every actual house has its address (which includes the number, the name of the street, city), every single point on the surface of earth can be specified by the latitude and longitude coordinates (lat & lng).

For example you see the location Bonnaud on the map above, we convert them to lat and long:

Coords: lat 46.621 lng 5.434 :Bonnaud, Val-Sonnette, Lons-le-Saunier, Jura, Bourgogne-Franche-Comté, France métropolitaine, 39190, France importance: 0.7350

Therefore, by using latitude and longitude we can specify virtually any point on earth, also like Delphi:

  • Geographic coordinates of Delphi, Greece
  • Latitude: 38°28’45” N Longitude: 22°29’36” E
  • Elevation above sea level: 560 m = 1837 ft

OpenStreetMap

So how I did this? With the OpenStreetMap API Nominatim.

The OSM Nominatim is a search engine for OpenStreetMap data. From this site you may search for a name or address (like Route de Bonnaud, Bonnaud, France), or look up place names by geographic coordinates. Each result will link to details page where you can inspect what data about the object is saved in the database and investigate how the address of the object has been computed (URI and JSON for example):

function TAddressGeoCodeOSM(faddress: string): string;
var
  url, res, display: string;
  jo, location: TJSONObject;
  urlid: TIduri; windown: TWinApiDownload;
 begin
  urlid:= TIdURI.create('');
  url:= urlid.URLEncode('https://nominatim.openstreetmap.org/search?
                                             format=json&q='+fAddress);
  windown:= TWinApiDownload.create;
  windown.useragent:= 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1'; 
  windown.url:= url;
  windown.download1(res);
  //windown.OnWorkStart
  StrReplace(res, '[{', '{');
  jo:= TJSONObject.create4(res);                   
  try
    if jo.getString('place_id') <> ' ' then               
      display:= jo.getstring('display_name');
    result:= Format('Coords: lat %2.3f  lng %2.3f  :%s  importance: %2.4f',
                   [jo.getdouble('lat'),jo.getdouble('lon'),display,
                                        jo.getdouble('importance')]);       
  except
    writeln('E: '+ExceptiontoString(exceptiontype, exceptionparam));                 
  finally                                  
    jo.Free;    
    urlid.free;
    windown.free;
  end; 
end;  

I use an URI, a JSON and a HTTPGet object and call the function:

writeln(‘res back_: ‘+TAddressGeoCodeOSM(‘Bonnaud, France’));

You should in particular verify that you have set a custom HTTP referrer or HTTP user agent (windown.useragent:=) that identifies your application, and that you are not overusing the service with massive bulk requests. Otherwise you get following message:

<p>You have been blocked because you have violated the<a href=”https://operations.osmfoundation.org/policies/nominatim/”>usage policy</a>of OSM’s Nominatim geocoding service. Please be aware that OSM’s resources are limited and shared between many users. The usage policy is there to ensure that the service remains usable for everybody.</p>

In case you missed the user agent, I passed it already with the constructor:

constructor TWinApiDownload.Create;
begin
  inherited;
  fUserAgent:= 'Mozilla/5.001(windows; U; NT4.0; en-US;) Gecko/25250101';
  fProgressUpdateInterval:= 100;
  fCachingEnabled:= True;
  fStop:= False;
  fActive:= False;
end;

So with OpenStreetMap the call is easy just to get an https:// and user agent to provide. OpenStreetMap (OSM) is a collaborative project to create a free editable map of the world. It is built by a community of mappers that contribute and maintain OSM data.

This REST endpoint is also used to reverse geocode, this is, generate an address from a latitude and a longitude. This is the format of the request:

  with TWinApiDownload.create do begin
     Useragent:= 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1'; 
     Url:= 'https://nominatim.openstreetmap.org/reverse?lat='
              +flots(flat)+'&lon='+flots(flong)+'&zoom=10&format=json';
     Download1(rest);
     //writeln(rest)
     with TJSONObject.create4(rest) do begin  
       writeln('display_name: '+getstring('display_name'));
       free;
     end;   
     free;  //ApiDown
   end;  

The double with statement is functional programming, the rest variable is a stringstream in Download1(rest); and we free the 2 objects immediately.

A geocoding service (also called an address locator) is a program that allows for a user to input a batch of data contained in a table, search for matches as compared to a reference table, and output the result in a map or GIS layer format. Now we can turn our geocoding coordinates in a map:

latlong.net

Two attributes in OSM are of interest, the zoom and the importance. Renderers can’t display on a map in each zoom level, so they have to make a selection. The more important an object is, the earlier (in zooming in) the object should be rendered. Also the this key “importance” with a value which refers to the area this object is important for, e.g. regional or urban:

res back_: Coords: lat 46.62084 lng 5.43424 :Bonnaud, Val-Sonnette, Lons-le-Saunier, Jura, Bourgogne-Franche-Comté, France métropolitaine, 39190, France importance: 0.7350
https://www.latlong.net/c/?lat=46.617&long=5.430
Pic: 93_mX4mapbox_osm_bonnaud_referencemap.jpg
Pic: 93_mX4mapbox_weatherapp_bonnaud_sat_reference.jpg

By the way you can simply open the map in maXbox with the command:

OpenWeb(‘https://www.latlong.net/c/?lat=46.617&long=5.430‘);

Currently there are many options to choose from when geocoding batches of address data. Lets turn our interest to commercial Services. We all know Google or the Google Maps Platform: This Geocoding API can be used to geocode worldwide addresses after obtaining an API key. You will need to enter a credit card to set up a billing account with Google, and they will give you $200/month credit for the first 12 months (view their pricing structure). They will not charge you until you give them permission to. You may also apply for additional educational credit up to $250/month. In case you don’t have a valid billing:

Exception: TJSONObject["status--\u0020You\u0020must\u0020enable\u0020Billing\u0020on\u0020the\u0020Google\u0020Cloud\u0020Project\u0020at\u0020https\u003A//console.cloud.google.com/project/_/billing/enable\u0020Learn\u0020more\u0020at\u0020https\u003A//developers.google.com/maps/gmp-get-started"] not found.

Geocodio

Geocoding (also known as forward geocoding) allows you to convert one or more addresses into geographic coordinates (i.e. latitude and longitude). Geocoding will also parse the address and append additional information (e.g. if you specify a zip code, Geocodio will return the city and state corresponding zip code as well).

Geocodio supports geocoding of addresses, cities and zip codes in various formats. Geocodio provides bulk geocoding and reverse lookup services through a REST API. The API is able to process a single address, as well as handle bulk requests of up to 10,000 addresses. The results are returned with an accuracy score indicating the confidence Geocodio has in the accuracy of the result. It is also able to parse addresses into individual components.

So I started with Geocodio https://www.geocod.io/docs/#geocoding and registered to get an API Key. Geocodio’s RESTful API allows you to perform forward and reverse geocoding lookups. They support both batch requests as well as individual lookups, but and this is the disadvantage, for the moment only for USA and Canada.

The base API url is https://api.geocod.io/v1.7/.

All HTTP responses (including errors) are returned with JSON-formatted output. For the code I tested with Python and maXbox with an Wininet and JSON Object:

function TAddressGeoCoding4(faddr, fcountry: string): String;
var
  Url,API_KEY, source: string;
  jo, locate: TJSONObject;
  urlid: TIdURI; 
  fLat,fLong: double;
begin
  urlid:= TIdURI.create('');
  API_KEY:='785b4141b...................'; //get your own one please
  if fcountry <> '' then
    Url:= urlid.URLEncode('https://api.geocod.io/v1.7/geocode?q='+
                          fAddr+'&country='+fcountry+'&api_key='+API_KEY) else
    Url:= urlid.URLEncode('https://api.geocod.io/v1.7/geocode?q='+
                          fAddr+'&api_key='+API_KEY);                                      
   
  jo:= TJSONObject.Create4(wdc_WinInet_HttpGet2(Url,Nil));
  try
    jo.getString('input')
    locate:= jo.getJSONArray('results').getJSONObject(0).getJSONObject('location');
    source:= jo.getJSONArray('results').getJSONObject(0).getString('source');
    //geometry.getJSONObject('coordinates');
    fLat:= locate.getDouble('lat') 
    fLong:= locate.getDouble('lng');
    result:=Format('Coordinates: lat %2.3f lng %2.3f :%s',[flat,flong,source]);
  except
    Xraise(Exception.Create(jo.getString('error')));
  finally                                      
    jo.Free;       
    urlid.free;
  end;  
end;  

You can test your REST-Call direct in the browser with:

Or you choose a map one tester online: https://www.geoapify.com/geocoding-api

One note to the code function above. I pass and address optional the country (to prevent name conflicts) to get the coordinates from the location:

writeln(TAddressGeoCoding4('Ontario','Canada'));

In most cases, the standard output format would be used. In certain situations, it can however be beneficial to work with a JSON structure that is specifically designed for your use case.

writeln(TAddressGeoCoding4('Halifax','Canada'));
display_name: Halifax, Halifax Regional Municipality, Halifax County, Nova Scotia, Canada
debug hash 7861896
Coordinates: lat 44.649 lng -63.586 :CanVec+ by Natural Resources Canada

The interesting part is the line in a oneliner:

jo:= TJSONObject.Create4(wdc_WinInet_HttpGet2(Url,Nil));

with the constructor to pass the httpget2 which returns the json result in one line to the TJSONObject.

If a JSON object is posted, you can specify a custom key for each element of your choice. This can be useful to match queries up with your existing data after the request is complete. If using a JSON array, results are guaranteed to be returned in the same order as they are requested.

The Geocodio API implements the concept of “warnings”. This is meant to assist and guide developers when implementing our API. But I checked also the error as Json field in the try except catch. To prevent misleading, inconsistent or duplicated locations like Cologne, Paris or Bern all over the world we should also check the source as identity authentication too.

Golf Region

If a city is provided without a state, Geocodio will automatically guess and add the state based on what it is most likely to be. Geocodio also understands shorthand’s for both streets and cities, for example NYC, SF, etc., are acceptable city names. Each geocoded result is returned with an accuracy score (like the importance in OpenStreetMap), which is a decimal number ranging from 0.00 to 1.00. This score is generated by an internal Geocodio engine based on how accurate the result is believed to be. The higher the score, the better the result. Results are always returned ordered by accuracy score.

Conclusion

Geocoded locations expressed in latitude, longitude coordinates can be obtained one at a time in web maps such as OSM, Geocodio, Bing Maps or Google Maps. Reverse geocoding is the process of converting latitude and longitude into a street address. The relative ease of geocoding and resulting accuracy can vary widely depending on a number of factors. What is the nature or the source of the data? How accurate is it and what format is it in? What geocoding technique will be used like REST or batch or scripts? Determining a geocoding strategy that best suits a particular need is not always clear.

The key to confidently geocoding data lies in understanding the reference table of the GIS which the data is being matched to, how a match is found, and the resulting spatial accuracy.

Call the script

Scriptname: 1108_CAI_GeocodingTWininetAPI_Maponly.pas

https://www.latlong.net/c/?lat=46.617&long=5.430

Geocoding topics and Script

Author: Max Kleiner, April 2022
Sierpinski 3D

URL Scanning

Our APIs allow you to submit URLs for scanning and retrieve the results once the scan has finished. Furthermore, you can use an API for searching existing scans by attributes such as domains, IPs, Autonomous System (AS) numbers, hashes, etc., we start with the simple search API without registration and key:

procedure getURLScan_API(ftopic: string);
 var res, aurl: string; i:integer;
     urid: TIdURI; 
 begin
 urid:= TIdURI.create('');
 aUrl:= urid.URLEncode('https://urlscan.io/api/v1/search/?q='+
                                                         'domain:'+ftopic)
 with TWinApiDownload.create do begin
    Useragent:= 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1'; 
    Url:= aUrl;
    Download1(res);
    //writeln(res)
    with TJSONObject.create4(res) do begin 
      //writeln(tostring2(2,3))
      if getstring('results') <> '' then
       for i:= 0 to getJSONArray('results').length-1 do begin 
         writeln(itoa(i)+':'+getJSONArray('results').getJSONObject(i).getString('_id'));
         writeln(itoa(i)+':'+getJSONArray('results').getJSONObject(i).getString('stats'));
       end; 
      free;  //JSON
    end;   
   free; //ApiDownload
  end;
  urid.Free;
 end; 

You can use the same ElasticSearch syntax to search for scans as on the Search page. Each result has high-level metadata about the scan result and a link to the API for the full scan result.

The search API returns an array of results (for i:= 0 to getJSONArray(‘results’).length-1) where each entry includes these items: _idThe UUID of the scan sortThe sort key, to be used with search_after pageInformation about the page after it finished loading taskParameters for the scan statsHigh-level stats about the page brandPro Only Detected phishing against specific brands

_id   The UUID of the scan
sort  The sort key, to be used with search_after 
page  Information about the page after it finished loading 
task  Parameters for the scan 
stats High-level stats about the page 
brand Pro Only Detected phishing against specific brands

For comprehensive list of available searchable fields, consult the urlscan.io Search API Reference.

URLScan of altavista.com

API search will find Public scans performed by anyone as well as Unlisted and Private scans performed by you or your teams.

To get all servers of a page in a prime domain:

procedure getURLScan_API2(ftopic: string);
 var res, aurl: string; i:integer;
     urid: TIdURI; joa: TJSONArray;
 begin
 urid:= TIdURI.create('');
 aUrl:= urid.URLEncode('https://urlscan.io/api/v1/search/?q='+
                                                   'domain:'+ftopic)
 with TWinApiDownload.create do begin
   Useragent:= 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1'; 
   Url:= aUrl;
   Download1(res);
   with TJSONObject.create4(res) do begin 
     if getstring('results') <> '' then begin
       joa:= getJSONArray('results');
       for i:= 0 to joa.length-1 do 
        writeln(itoa(i)+':'+
          joa.getJSONObject(i).getJSONObject('page').getString('server'));
       free;  //JSON
     end;
   end;   
   free; //ApiDownload
  end;
  urid.Free;
 end; 
0:Apache/2.2.22 (Fedora)
1:Apache
2:Apache
3:Apache
4:Apache
5:Apache/2.4.25 (Debian)
6:Apache/2.4.41 (Unix)
7:GSE
8:Apache/2.2.22 (Fedora)
9:nginx/1.12.1
10:.V15 Apache
11:Apache
12:guce
13:ip-10-123-122-59.ec2.internal
14:Apache
15:Apache/2.2.22 (Fedora)
16:ATS
17:LiteSpeed
18:guce
19:Microsoft-IIS/10.0
20:ATS
21:Apache
22:Apache
23:Apache
24:Apache/1.3.42 (Unix) FrontPage/5.0.2.2635 PHP/5.2.17 mod_ssl/2.8.31 OpenSSL/0.9.8y
25:guce
26:guce
27:guce
28:ATS
29:LiteSpeed
30:Apache
31:.V15 Apache
32:Apache/2.2.22 (Fedora)
33:guce
34:.V18 Apache .....
61:Apache/2.4.41 (Unix)
62:Squeegit/1.2.5 (3_sir)
63:Apache/2.4.25 (Debian)
64:Microsoft-IIS/10.0
IP Geolocation is the identification of the geographic location of a device, such as a mobile phone, gadget, laptop, server and so on, by using an IP address.
function getURLScan_Geo2IP(ftopic: string): string;
var res, aurl: string; i:integer;
    urid: TIdURI; joa: TJSONArray;
begin
urid:= TIdURI.create('');
aUrl:= urid.URLEncode(GEOAPIURL+'ipgeo?ip='+ftopic+'&apiKey='+GEOAPIKEY)
with TWinApiDownload.create do begin
  Useragent:= 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1'; 
  Url:= aUrl;
  Download1(res);
  //result:= res;
  with TJSONObject.create4(res) do begin 
     try
       result:= getString('ip');
       result:= result+':IP '+getString('country_capital');
       result:= result+' '+getString('latitude');
       result:= result+' '+getString('longitude');
     except
       writeln(ExceptionToString(ExceptionType, ExceptionParam));
     end;     
    free;  //JSON
  end;//*)   
  free; //ApiDownload
 end;
 urid.Free;
end; 

We call that function with a whatismyip service:
writeln(‘Geo location: ‘+getURLScan_Geo2IP(GetHTM(‘http://ipinfo.io/ip&#8217;)));

Result: myip test: 46.127.119.188
{"ip":"46.127.119.188","continent_code":"EU","continent_name":"Europe","country_code2":"CH","country_code3":"CHE","country_name":"Switzerland","country_capital":"Bern","state_prov":"Zurich","district":"Kreis 1","city":"Zurich","zipcode":"8001","latitude":"47.36916","longitude":"8.54374","is_eu":false,"calling_code":"+41","country_tld":".ch","languages":"de-CH,fr-CH,it-CH,rm","country_flag":"https://ipgeolocation.io/static/flags/ch_64.png","geoname_id":"6518144","isp":"Liberty Global B.V.","connection_type":"","organization":"Liberty Global B.V.","currency":{"code":"CHF","name":"Swiss Franc","symbol":"CHF"},"time_zone":{"name":"Europe/Zurich","offset":1,"current_time":"2022-05-23 16:51:01.115+0200","current_time_unix":1653317461.115,"is_dst":true,"dst_savings":1}}

Geo location: 46.127.119.188:IP Bern 47.36916 8.54374
this © is Papiermühlestrasse
mX4 executed: 23/05/2022 16:50:59 Runtime: 0:0:2.185 Memload: 38% use

var geoStream: TMemoryStream;
//try direct functional
  geoStream:= TMemoryStream.Create;
  try
    HTTPget(GEOAPIURL+'ipgeo?ip='+GetHTM('http://ipinfo.io/ip')+
                              '&apiKey='+GEOAPIKEY, geoStream)
    writeln(StreamtoString3(geostream));
  except
    showmessage('E.message')
  finally
    geoStream.free;  
  end  //*)
geo plot lot
too hot for code
14 days later

Geocoding

Geocoding (also known as forward geocoding) allows you to convert one or more addresses into geographic coordinates (i.e. latitude and longitude). Geocoding will also parse the address and append additional information (e.g. if you specify a zip code, Geocodio will return the city and state corresponding the zip code as well).

Geocodio supports geocoding of addresses, cities and zip codes in various formats.

Geocodio provides bulk geocoding and reverse lookup services through a REST API. The API is able to process a single address, as well as handle bulk requests of up to 10,000 addresses. Geocoded results are returned with an accuracy score indicating the confidence Geocodio has in the accuracy of the result. Geocodio is also able to parse addresses into individual components.

Geographic coordinates of Delphi, Greece
Latitude: 38°28’45” N
Longitude: 22°29’36” E
Elevation above sea level: 560 m = 1837 ft

Geographic coordinates of Bern, Switzerland
Latitude: 46°56’53” N
Longitude: 7°26’50” E
Elevation above sea level: 549 m = 1801 ft

First I tried with Google Maps:

One of many Geocoding APIs

Then I got the message to bill something with credit card an I denied:

Exception: TJSONObject["status--\u0020You\u0020must\u0020enable\u0020Billing\u0020on\u0020the\u0020Google\u0020Cloud\u0020Project\u0020at\u0020https\u003A//console.cloud.google.com/project/_/billing/enable\u0020Learn\u0020more\u0020at\u0020https\u003A//developers.google.com/maps/gmp-get-started"] not found.

So I started with Geocodio https://www.geocod.io/docs/#geocoding and registered to get an API Key.

Geocodio’s RESTful API allows you to perform forward and reverse geocoding lookups. We support both batch requests as well as individual lookups.

You can also optionally ask for data appends such as timezone, Congressional districts or similar things of that nature.

The base API url is https://api.geocod.io/v1.7/.

All HTTP responses (including errors) are returned with JSON-formatted output. For the code I tested with Python and maXbox with an Wininet and JSON Object:

function TAddressGeoCoding4(faddr, fcountry: string): String;
var
  Url,API_KEY, source: string;
  jo, locate: TJSONObject;
  urlid: TIdURI; 
  fLat,fLong: double;
begin
  urlid:= TIdURI.create('');
  API_KEY:='785b4141b...................'; //get your own one please
  if fcountry <> '' then 
    Url:= urlid.URLEncode('https://api.geocod.io/v1.7/geocode?q='+
                          fAddr+'&country='+fcountry+'&api_key='+API_KEY) else
    Url:= urlid.URLEncode('https://api.geocod.io/v1.7/geocode?q='+
                          fAddr+'&api_key='+API_KEY);                                      
  
  jo:= TJSONObject.Create4(wdc_WinInet_HttpGet2(Url,Nil));
  try
    jo.getString('input')
    locate:= jo.getJSONArray('results').getJSONObject(0).getJSONObject('location');
    source:= jo.getJSONArray('results').getJSONObject(0).getString('source');
    //geometry.getJSONObject('coordinates');
    fLat:= locate.getDouble('lat') 
    fLong:= locate.getDouble('lng');
    result:=Format('Coordinates: lat %2.3f lng %2.3f :%s',[flat,flong,source]);
  except
    Xraise(Exception.Create(jo.getString('error')));
  finally                                       
    jo.Free;       
    urlid.free;
  end;  
end;  

You can test your REST-Call direct in the browser with: https://api.geocod.io/v1.7/geocode?q=cologne&api_key=785b4141b&#8230;

Or you choose a map one tester online: https://www.geoapify.com/geocoding-api

One note to the code function above. We pass and adress and optional the country (to prevent name conflicts) to get the coordinates from the location:

In most cases, the standard output format would be used. In certain situations, it can however be beneficial to work with a JSON structure that is specifically designed for your use case.

writeln(TAddressGeoCoding4('Ontario','Canada'));
>>> Coordinates: lat 50.445 lng -86.047 :CanVec+ by Natural Resources Canada

The intersting part is jo:= TJSONObject.Create4(wdc_WinInet_HttpGet2(Url,Nil)); with the constructor to pass the httpget2 which returns the json result in one line to the json-object.

If a JSON object is posted, you can specify a custom key for each element of your choice. This can be useful to match queries up with your existing data after the request is complete. If using a JSON array, results are guaranteed to be returned in the same order as they are requested.

Reverse geocoding is the process of converting latitude and longitude into a street address.

Geocodio will find matching street(s) and determine the correct house number based on the location. Note that Geocodio does not guarantee to return a valid house number; it is our closest approximation.

After some calls we get an overview of the usage:

Geocodio Dashboard

The Geocodio API implements the concept of “warnings”. This is meant to assist and guide developers when implementing our API. But I checked also the error as Json field in the try except catch. To prevent misleading, inconsistent or duplicated locations like Cologne, Paris or Bern all over the world we should also check the source as identity authentication too:

try
  jo.getString('input')
  locate:= jo.getJSONArray('results').getJSONObject(0).getJSONObject('location');
  source:= jo.getJSONArray('results').getJSONObject(0).getString('source');
  fLat:= locate.getDouble('lat') 
  fLong:= locate.getDouble('lng');
  result:=Format('Coordinates: lat %2.3f lng %2.3f :%s',[flat,flong,source]);
except
  Xraise(Exception.Create(jo.getString('error')));
finally            

If a city is provided without a state, Geocodio will automatically guess and add the state based on what it is most likely to be. Geocodio also understands shorthands for both streets and cities, for example NYC, SF, etc., are acceptable city names.

json array and objects in browser view

All results come with an address_components dictionary. This is an overview of all of the possible keys that you may find. The API is public for more insights:

https://github.com/Geocodio/openapi-spec/blob/master/geocodio-api.yml

The Geocodio API is continuously improved. Most updates require no changes for API users, but in some cases we might have to introduce breaking changes. Each geocoded result is returned with an accuracy score, which is a decimal number ranging from 0.00 to 1.00. This score is generated by the internal Geocodio engine based on how accurate the result is believed to be. The higher the score, the better the result. Results are always returned ordered by accuracy score.

The script in maXbox or https://pypi.org/project/pygeocodio/

More docs on: https://www.geocod.io/docs/#geocoding

OpenStreetMap

With OpenStreetMap the call is easy just to get an https and user agent to provide:

var winsets: TNetUtilsSettings; destfile: widestring; msst: TStringstream;
url:= urlid.URLEncode('https://nominatim.openstreetmap.org/search?format=json&q=fAddr);   
winsets.UserAgent:= Cuseragent;
msst:= TStringStream.create('');   
writeln(botostr(InetDownload(Url, msst,  Nil)));
jo:= TJSONObject.Create4(msst.datastring);
writeln(jo.getstring('lat')); 
[{"place_id":282193469,"licence":"Data © OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright","osm_type":"relation","osm_id":62578,"boundingbox":["50.8304399","51.0849743","6.7725303","7.162028"],"lat":"50.938361","lon":"6.959974","display_name":"Cologne, North Rhine-Westphalia, Germany","class":"boundary","type":"administrative","importance":0.9006323589104861,"icon":"https://nominatim.openstreetmap.org/ui/mapicons//poi_boundary_administrative.p.20.png"}]
function TAddressGeoCodeOSM(faddress: string): string;
var
  url, res, display : string;
  jo, location: TJSONObject;
  urlid: TIduri; windown: TWinApiDownload;
 begin
  urlid:= TIdURI.create('');
  url:= urlid.URLEncode('https://nominatim.openstreetmap.org/search?format=json&q='+
                                                                fAddress);
  writeln(url)
  windown:= TWinApiDownload.create;
  windown.useragent:= 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1'; 
  windown.url:= url;
  writeln('check url '+itoa(windown.CheckURL(url)));      
  windown.download1(res);
  //windown.OnWorkStart
  StrReplace(res, '[{', '{');
  jo:= TJSONObject.create4(res);                   
  try
    if jo.getString('place_id') <> ' ' then               
      display:= jo.getstring('display_name');
    result:= Format('Coords: lat %2.3f  lng %2.3f  :%s  importance: %2.4f',
                  [jo.getdouble('lat'),jo.getdouble('lon'),display,
                                       jo.getdouble('importance')]);       
  except
    writeln('E: '+ExceptiontoString(exceptiontype, exceptionparam));                 
  finally                                  
    jo.Free;    //((*)
    urlid.free;
    windown.free;
  end; 
end;  

TEE Gottardo Koblenz
Remote Session on a Ubuntu16 to test GeoCoding GeoFence

OpenStreetMap (OSM) is a collaborative project to create a free editable map of the world. It is built by a community of mappers that contribute and maintain OSM data.

This endpoint is used to reverse geocode, this is, generate an address from a latitude and a longitude. This is the format of the request:

  with TWinApiDownload.create do begin
     Useragent:= 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1'; 
     Url:= 'https://nominatim.openstreetmap.org/reverse?lat='
                      +flots(flat)+'&lon='+flots(flong)+'&zoom=10&format=json';
     Download1(rest);
     //writeln(rest)
     with TJSONObject.create4(rest) do begin  
       writeln('display_name: '+getstring('display_name'));
       free;
     end;   
     free;  //ApiDownload
   end;  
display_name: Halifax, Halifax Regional Municipality, Halifax County, Nova Scotia, Canada
Coordinates: lat 44.649 lng -63.586 :CanVec+ by Natural Resources Canada

You need an user agent, the double with statement is functional programming, the rest var is a stringstream and we free the 2 objects immediatly. If you want to start using the Nominatim API with Python or Pascal, take a look at this GitHub Gist with examples.

TEE Mistral

Test Referenz:

Lat Long
(44.649000, -63.586000)
GPS Coordinates
44° 38′ 56.4” N 63° 35′ 9.6” W
5741 Cogswell Street, Halifax NS B3K
Halifax Nova Scotia Canada

https://www.google.com/maps/place/44%C2%B039’03.4%22N+63%C2%B037’25.0%22W/@44.650948,-63.625805,17z/data=!3m1!4b1!4m5!3m4!1s0x0:0xe41c9d93a44dd274!8m2!3d44.650948!4d-63.623611

Fibonacci
Sunflower
Example: 1117_U_SolarPos2.pas
Geocoding with XMLHTTP.6.0 /gzip
ADE 80 106-2
NS Startrain 1311
Rheingold or Rembrandt
Numberriddle
Geocoding out of the maXbox
Geocoding Web Spyder
Space Race
Borland Magazin 5/94

Synthetic Data

/////////////////////////////////////////////////////////////

Synthetic Data Generator

______________________________________________________________________________

maXbox Starter91 – Build with P4D and SynDat

Make the fake.

Real data, extracted from the real world, is a gold standard for data science and data protection, perhaps for obvious reasons.

In such a case, synthetic data producing can be used either in place of real data, protect real user as an avatar or to augment an insufficiently large dataset. With Python4Delphi scripting.

http://www.softwareschule.ch/examples/pydemo32_2.txt

Faker is a Python library1 that generates fake data. Fake data is often used for testing or filling databases with some dummy data. Faker is strong inspired by PHP’s Faker, Perl’s Data::Faker, and Ruby’s Faker.

As a pdf: http://www.softwareschule.ch/download/maxbox_starter91_1.pdf

We are also able to sample from a model and create synthetic data, hence the name SynDat. The most obvious way that the use of synthetic data benefits data science is that it reduces the need to capture data from real-world events, and for this reason it becomes possible to generate data and construct a dataset much more quickly than a dataset dependent on real-world events and in addition you don’t misuse data protection.

SynDat Concept

_PIC: 101_syndat_concept.png

Now I want to show almost step by step how we can use the Faker Lib. First you had to install faker package, it can be installed with pip:

C:\Users\Max\AppData\Local\Programs\Python\Python36-32>

python -m pip install faker

Install a 32 bit package module in a 64 bit environment:

1. Change to your 32 bit path with cd:

C:\Users\Max\AppData\Local\Programs\Python\Python36–32>

2. Call the Pip (e.g. faker module) explicitly with
python.exe: python -m pip install faker

And it runs:

Downloading https://files.pythonhosted.org/packages/27/ab/0371598513e8179d9053911e814c4de4ec2d0dd47e725dca40aa664f994c/Faker-9.9.0-py3-none-any.whl (1.2MB)..

You are using pip version 9.0.1, however version 21.3.1 is available. You should consider upgrading via the ‘python -m pip install –upgrade pip’. C:\Users\Max\AppData\Local\Programs\Python\Python36-32> >>>>>>>>>>>

Now we start the program:

The fake.Faker (fake = Faker()) creates and initializes a faker generator, which can generate data by accessing properties named after the type of data, whether you need to bootstrap your database, create structured JSON documents or fill-in your storage persistence to stress test.

To clean up the data, we will also replace the newlines as \n in the generated addresses with commas or CRLF, and remove the newlines from profile generated text completely.

sw:= TStopWatch.Create();
sw.Start;
eg.execStr('from faker import Faker');
eg.execStr('import simplejson as json'); //# instead import json
eg.execStr('import dumper');
eg.execStr('fake = Faker()');
fprofile:= eg.evalStr('(fake.profile())')
fprofile:= StringReplace(fprofile,'\n',CRLF,[rfReplaceAll]);

Faker delegates the data generation to providers. The default provider uses the English locale. Faker supports other locales; they differ in level of completion, there are lots of ways to artificially manufacture and build data, some of which are far more complex than others and models real-world distribution with descriptive statistics.

Check the output with path and list the profile dictionary, the example outputs a fake name, address, and many more items of a persons profile:

fake person profile:
APO AA 42693', 'current_location': (Decimal('-51.8228245'), Decimal('-61.889364')), 'blood_group': 'A+', 'website': ['http://www.jones-clark.net/', 'https://www.fowler.com/'], 'username': 'garciatina', 'name': 'Roger Nichols', 'sex': 'M', 'address': '51574 Combs Alley Apt. 142, Ryanhaven, AL 82796', 'mail': 'andrea31@hotmail.com', 'birthdate': datetime.date(1914, 4, 15)} creditcard#: 213140049750943

Stop Watch Faker Tester1: 0:0:0.636

This is not json as I first assumed, and we can convert it. I tried first with json and simplejson, got some date and decimals serialize exceptions (Object of type date is not JSON serializable.), then I used dumper lib, but got a next exception Exception: <class ‘AttributeError’>: ‘NoneType’ object has no attribute ‘write’.: So the profile is a dict type, the misleading {} trapped me first. Let’s generate another avatar:

{‘job’: ‘Nurse, adult’, ‘company’: ‘Rogers and Sons’, ‘ssn’: ‘038-06-4652’, ‘residence’: ‘PSC 8856, Box 2882

APO AE 08426′, ‘current_location’: (Decimal(‘16.4363075’), Decimal(‘-83.079826’)), ‘blood_group’: ‘A-‘, ‘website’: [‘https://www.white.biz/&#8217;, ‘http://garrett-perez.com/’%5D, ‘username’: ‘xnelson’, ‘name’: ‘Ms. Colleen Bowman PhD’, ‘sex’: ‘F’, ‘address’: ‘328 Reeves Estates Apt. 279 Lake Nicholas, MD 31753’, ‘mail’: ‘kkhan@yahoo.com’, ‘birthdate’: datetime.date(1936, 6, 3)}

Oh what as surprise a nurse and she holds a PhD and works by Rogers. What if, for instance, I’m interested in generating German or Spanish names and professions of the type one would find in Netherlands, Mexico, Austria or Switzerland?

fake = Faker(['de_DE'])
for i in range(10):
   print(fake.name())

eg.execStr('fake = Faker(["es_MX"])')
//for i in range(10):
 for it:= 1 to 10 do
   println(UTF8toAnsi(eg.evalStr('fake.name()')));
>>> Alma María José Montañez Dávila ... 

The Faker constructor takes also a performance-related argument called use_weighting. It specifies whether to attempt to have the frequency of values match real-world frequencies and distribution shape (e.g. the English name Gary would be much more frequent than the name Welson). If use_weighting is False, then all items have an equal chance of being selected, and the selection process is much faster; the default is True.

The next line is a simple demonstration of Faker credit card:

   println('creditcard#: '+eg.evalStr('fake.credit_card_number()')); //}
   sw.Stop;

Faker also support for dummy hashes and uuids for SynDat:

#!/usr/bin/env python

from faker import Faker

faker = Faker()

print(f’md5: {faker.md5()}’)
print(f’sha1: {faker.sha1()}’)
print(f’sha256: {faker.sha256()}’)
print(f’uuid4: {faker.uuid4()}’)

from faker import Faker
faker = Faker()
print(f'md5: {faker.md5()}')
print(f'sha1: {faker.sha1()}')
print(f'sha256: {faker.sha256()}')
print(f'uuid4: {faker.uuid4()}')

In the end we close and free all the resources of objects and net-connections, including stop-watcher sw and python frame apd:

except
  eg.raiseError;
  writeln(ExceptionToString(ExceptionType, ExceptionParam));
finally
  eg.Free;
  sw.Free;
  sw:= Nil;
  apd.position:= 100;
end;

You can also run the Python Engine script at runtime to get a Faker() object and if something went wrong you got a raiseError Py exception. Eval() function accepts a string argument and if the string argument is an expression then eval() will evaluate the expression as a callback with return (faker.proxy.Faker):

with TPythonEngine.Create(Nil) do begin
  pythonhome:= PYHOME;
  try
    loadDLL;
    Println('Faker Platform: '+ 
          EvalStr('__import__("faker").Faker()')); 
  except
    raiseError;        
  finally       
    free;
  end; 
end;  

>>> <faker.proxy.Faker object at 0x0CAFA850>

A GUID is an acronyom that stands for Globally Unique Identifier, they are also referred to as UUIDs or Universaly Unique Identifiers – there is no real difference between the two. We get the GUID from the kernel generator in a compact way:

function CreateCompactGuidStr: string;
var
  LIndex: Integer;
  LBytes: TBytes;
  NewGUID: TGUID;
begin
  Result := '';
  //LBytes:= TGUID.NewGuid.ToByteArray();
   NewGUID:= StringToGUID(CreateClassID);
   LBytes:= TBytes(GuidtoString(NewGuid));
   for LIndex:= 0 to Length(LBytes)-1 do
     Result:= Result + IntToHex(LBytes[LIndex], 2);
end;

Conclusion

In this report, we used Python Faker to generate fake or synthetic data in Python and maXbox with measuring time behaviour.

SynDat Concept Flow

Finally, synthetic datasets can minimize privacy concerns. Attempts to anonymize data can be ineffective, as even if sensitive/identifying variables are removed from the dataset, other variables can act as identifiers when they are combined. This isn’t an issue with synthetic data, as it was never based on a real person, or real event, in the first place.

A concept could mean, firms, institutes or simply users don’t deal with real person data, they got an avatar which makes an relationship between a hash and a guid in a worldwide proxy block-chain (pb1). A real person is protected behind the SynDat proxy with a guid record.

Python for .NET is also a package that gives Python programmers nearly seamless integration with the .NET Common Language Runtime (CLR) and provides a powerful application scripting tool for .NET developers and with Delphi or Lazarus just found that:

https://i2.wp.com/blogs.embarcadero.com/wp-content/uploads/2021/07/demo01_Faker2-2809487.png?ssl=1

SynDat Faker Script

_PIC: 101_syndat_gui_profile.png

Faker and Classification in Repl Environment

Hint: A minimal semantic check is done, e.g. if a person is older than 80 he get no job record, but the other way round if a person is about 4 years old he got a job?

fake person profile:
{‘job’: ‘Legal secretary’, ‘company’: ‘Dixon-Fowler’, ‘ssn’: ‘066-04-0047’, ‘residence’: ‘PSC 2835, Box 4921
APO AA 40255′, ‘current_location’: (Decimal(‘7.0670085’), Decimal(‘117.638907’)), ‘blood_group’: ‘AB-‘, ‘website’: [‘https://www.white.com/&#8217;, ‘https://www.arnold.org/&#8217;, ‘https://www.miller.com/&#8217;, ‘http://pope.biz/’%5D, ‘username’: ‘nguyenchristopher’, ‘name’: ‘Thomas Alexander’, ‘sex’: ‘M’, ‘address’: ‘00176 Mary Point
North Laura, GA 45319′, ‘mail’: ‘bthompson@yahoo.com’, ‘birthdate’: datetime.date(2019, 12, 16)}

SynDat topics and script:

Top Release 4.7.6


Release Notes maXbox 4.7.6.10 IV Jan. 2022 mX476


Add 25 Units + 6 Tutorials

1441 unit uPSI_neuralgeneric.pas; CAI
1442 unit uPSI_neuralthread.pas; CAI
1443 unit uPSI_uSysTools; TuO
1444 unit upsi_neuralsets; mX4
1445 unit uPSI_uWinNT.pas mX4
1446 unit uPSI_URungeKutta4.pas ICS
1447 unit uPSI_UrlConIcs.pas ICS
1448 unit uPSI_OverbyteIcsUtils.pas ICS
1449 unit uPSI_Numedit2 mX4
1450 unit uPSI_PsAPI_3.pas mX4
1451 unit uPSI_SeSHA256.pas
1452 unit IdHashMessageDigest_max2;
1453 unit uPSI_BlocksUnit.pas
1454 unit uPSI_DelticsCommandLine.pas
1455 unit uPSI_DelticsStrUtils;
1456 unit uPSI_DelticsBitField;
1457 unit uPSI_DelticsSysUtils;
1458 unit uPSI_ALIniFiles2.pas
1459 unit uPSI_StarCalc2.pas
1460 unit uPSI_IdHashMessageDigest2.pas
1461 unit uPSI_U_Splines;
1462 unit uPSI_U_CoasterB.pas;
1463 U_SpringMass2.pas
1464 uPSI_MARSCoreUtils;
1465 unit uPSI_clJsonParser.pas

Total of Function Calls: 35371
SHA1: of 4.7.6.10 A2B2B2D1596C6A5F3ACCED90D0C2246172A3DE2C
CRC32: 285ACBCB 31.3 MB (32,921,928 bytes)

ZIP file maxbox4.zip sha1 E267EB40AA945AD10B88EF8274C837F510DD96D4

dinobox syndat

1 https://pypi.org/project/Faker/

Blockchain & Bitcoin Schema
batch coding to generate synthetic data

VCL4Python: Delphi’s VCL library as a Python module for building Windows GUI

P4D and VCL4P and vice versa

https://github.com/maxkleiner/DelphiVCL4Python

Testbed for SynDat