Reading json data in maXbox could be easy. Json data can be read from a file or it could be a json web link. Let us first try to read the json from a web link.
Const
JsonUrl = 'https://pomber.github.io/covid19/timeseries.json';
Let us first define the necessary packages “msxml2.xmlhttp and the JSON class”.
var XMLhttp : OleVariant; // As Object
ajt: TJson; JObj: TJsonObject2;
XMLhttp:= CreateOleObject('msxml2.xmlhttp')
XMLhttp.Open ('GET', JsonUrl, False)
ajt:= TJson.create();
Let us import the covid19 timeseries data from json link pomber.github.io/covid19/timeseries.json using XMLhttp:
Ref: <class 'pandas.core.frame.DataFrame'> RangeIndex: 76608 entries, 0 to 76607 Data columns (total 5 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 country 76608 non-null object 1 date 76608 non-null object 2 confirmed 76608 non-null int64 3 deaths 76608 non-null int64 4 recovered 76608 non-null int64 dtypes: int64(3), object(2) memory usage: 2.9+ MB
XMLhttp.setrequestHeader('Content-Type','application/x-www-form-urlencoded');
XMLhttp.Send();
response:= XMLhttp.responseText; //)
statuscode:= XMLhttp.status;
To get the json type of class, struct or array, we need to use ajt.parse() method first.
try
ajt.parse(resrange);
except
writeln( 'Exception: <TJson>"" parse error: {'+
exceptiontostring(exceptiontype, exceptionparam))
end;
//Split(ajt.Stringify,'{',slist)
writeln('Statuscode: '+(statuscode)+': '+'listlen '+itoa(ajt.count));
writeln('Slice jsons country: '+itoa(ajt.count))
JObj:= ajt.JsonObject;
writeln('Get all Countries: ')
for cnt:= 0 to jobj.count-1 do
//writeln(Jobj.items[cnt].name+' '+Jobj.items[cnt].value.stringify);
writeln(Jobj.items[cnt].name);
Ok, it is a JsonObject dictionary with 192 countries. Lets check the keys of our dict.
//*) //accumulated
Clabel:='Vietnam';
Chart1.Title.Text.clear;
Chart1.Title.Text.add('Sciplot TimeSerie for: '+Clabel);
JArray:= ajt.values[Clabel].asarray;
writeln('jitems country '+itoa(jarray.count));
for cnt:= 1 to jarray.count-1 do begin
itmp:= jarray.items[cnt].asObject.values['confirmed'].asinteger;
chart1.Series[0].Addxy(cnt,itmp,'',clGreen);
itmp:= jarray.items[cnt].asObject.values['deaths'].asinteger;
chart1.Series[1].Addxy(cnt,itmp,'',clRed);
itmp:= jarray.items[cnt].asObject.values['recovered'].asinteger;
chart1.Series[2].Addxy(cnt,itmp,'',clBlue);
end;
The script you can find at: http://www.softwareschule.ch/examples/covid2.txt
Conclusion: JSON (JavaScript Object Notation) is a lightweight data-interchange format. It is easy for humans to read and write. It is easy for machines to parse and generate.
Random Number Generator
A random number generator is a routine that produces a sequence of numbers that would pass statistical or probabilistic tests for randomness. To be really strict, routines that generate random numbers are said to be pseudorandom number generators (often abbreviated to PRNG) to differentiate them from true random number generators that rely on some kind of random events happening at a quantum level.
type
TStRandomBase = class
private
protected
function rbMarsagliaGamma(aShape : double) : double;
function rbMontyPythonNormal : double;
public
{uniform distributions}
function AsFloat : double; virtual; abstract;
function AsInt(aUpperLimit : integer) : integer;
function AsIntInRange(aLowerLimit : integer;
aUpperLimit : integer) : integer;
{continuous non-uniform distributions}
function AsBeta(aShape1, aShape2 : double) : double;
function AsCauchy : double;
function AsChiSquared(aFreedom : integer) : double;
function AsErlang(aMean : double;
aOrder : integer) : double;
function AsExponential(aMean : double) : double;
function AsF(aFreedom1 : integer;
aFreedom2 : integer) : double;
function AsGamma(aShape : double; aScale : double) : double;
function AsLogNormal(aMean : double;
aStdDev : double) : double;
function AsNormal(aMean : double;
aStdDev : double) : double;
function AsT(aFreedom : integer) : double;
function AsWeibull(aShape : double;
aScale : double) : double;
end;
TStRandomSystem = class(TStRandomBase)
private
FSeed : integer;
protected
procedure rsSetSeed(aValue : integer);
public
constructor Create(aSeed : integer);
function AsFloat : double; override;
property Seed : integer read FSeed write rsSetSeed;
end;
https://github.com/TurboPack/SysTools/blob/master/source/StRandom.pas
Often, in conversation, people use the term random when they really mean arbitrary. When one asks for an arbitrary number, one is saying that one doesn’t really care what number one gets: almost any number will do. By contrast, a random number is a precisely defined mathematical concept: every number should be equally likely to occur. A random number will satisfy someone who needs an arbitrary number, but not the other way around.
The first test is the simplest: the uniformity test. This is the one we were discussing earlier. Basically, the random numbers we generate are going to be checked to see that they uniformly cover the range 0.0 to 1.0. We create 100 buckets, generate 1,000,000 random numbers, and slot them into each bucket. Bucket 0 gets all the random numbers from 0.0 to 0.01, bucket 1 gets them from 0.01 to 0.02, and so on. The probability of a random number falling into a particular bucket is obviously 0.01. We calculate the chi-square value for our test and check that against the standard table, using the 99 degrees of freedom line.
{===Helper routines==============================================}
function GetRandomSeedX : integer;
var
Hash : integer;
SystemTime: TSystemTime;
G : integer;
begin
{start with the tick count}
Hash := integer(GetTickCount);
{get the current time}
GetLocalTime(SystemTime);
{hash in the milliseconds}
Hash := (Hash shl 4) + SystemTime.wMilliseconds;
G := Hash and Integer($F0000000);
if (G <> 0) then
Hash := (Hash xor (G shr 24)) xor G;
{hash in the second}
Hash := (Hash shl 4) + SystemTime.wSecond;
G := Hash and Integer($F0000000);
if (G <> 0) then
Hash := (Hash xor (G shr 24)) xor G;
{hash in the minute}
Hash := (Hash shl 4) + SystemTime.wMinute;
G := Hash and Integer($F0000000);
if (G <> 0) then
Hash := (Hash xor (G shr 24)) xor G;
{hash in the hour}
Hash := (Hash shl 3) + SystemTime.wHour;
G := Hash and Integer($F0000000);
if (G <> 0) then
Hash := (Hash xor (G shr 24)) xor G;
{return the hash}
Result := Hash;
end;
{===============================================================}
https://www.delphipower.xyz/data_structures/the_uniformity_test.html
SelfTestCRandom;
writeln('GetRandomSeedX: '+inttostr64(GetRandomSeedX));
strand:= TStRandomSystem.create(42); //if 0 then randomseedx
writeln(floattostr(strand.asFloat))
writeln(floattostr(strand.asFloat))
writeln(floattostr({System.}Random(10)));
writeln(floattostr({System.}RandomE));
writeln(itoa(strand.asInt(10000)))
writeln(itoa(strand.asInt(10000)))
writeln(itoa(strand.asInt($E15)))
UniformityTest2(strand, ChiSquare, DegsFreedom)
writeln('ChiSquare: '+floattostr(ChiSquare)+' ,degsfreedom:'+itoa(degsfreedom));
UniformityTest3(strand, ChiSquare, DegsFreedom)
writeln('ChiSquare: '+floattostr(ChiSquare)+' ,degsfreedom:'+itoa(degsfreedom));
strand.Free;
(Current theories state that quantum events are truly random. The time of the decay of a radioactive atom into its byproducts cannot be predicted; all we can say is that there is a certain probability that it will decay within a certain period of time, and we can estimate that probability by observing the decay of many, many atoms.)
File Size Proof
The FileSize test monitors the file size of each of the files specified as parameters to the test. The current size of the file in Kilobytes and alerts can be generated when a file exceeds a predefined maximum size.
function FileGetSizeX(const FileName: string): Int64;
{$ifndef fpc}
var FileInfo: TSearchRec;
{$endif}
begin
{$ifdef fpc}
Result:= FileUtil.FileSize(FileName);
{$else}
// from LCL FileUtil code
FileInfo.Name:= Filename;
FileInfo.FindHandle:= {Windows.}FindFirstFile({Windows.}{LPTSTR}
(FileInfo.Name),FileInfo.FindData);
if FileInfo.FindHandle={Windows.}Invalid_Handle_value then begin
Result:=-1;
Exit;
end;
Result:= (int64(FileInfo.FindData.nFileSizeHigh)
Shl 32)+ FileInfo.FindData.nFileSizeLow;
{Windows.}FindCloseW(FileInfo.FindHandle);
{$endif}
end;
writeln(inttostr64(FileGetSize(exepath+’maXbox4.exe’)));
writeln(inttostr64(FileGetSizeX(exepath+’maXbox4.exe’)));
println(int64tostr(CFileGetSize(exepath+’maXbox4.exe’)));
FileStream Handling
procedure Testbinaryload(afilepath: string);
var fs, fsc: TStream;
LoadString: AnsiString;
begin
fs:= TFileStream.Create(afilepath,
fmOpenReadWrite or fmShareDenyNone);
try
SetLength(LoadString, FS.Size);
writeln('filesize1 '+itoa(fs.size));
FS.ReadBuffer((LoadString), FS.Size);
//fs.Seek(0, sofromBeginning);
fs.Position:= 0;
fs.WriteBuffer(loadstring, fs.size);
finally
writeln('filesize2 '+itoa(fs.size));
fs.free;
end;
end;
Procedure TBackupFormFileCopy(Const sourcefilename,
targetfilename: String );
Var S, T: TFileStream;
Begin
S:= TFileStream.Create(sourcefilename, fmOpenRead );
try
T:= TFileStream.Create(targetfilename,
fmOpenWrite or fmCreate );
try
T.CopyFrom(S, S.Size );
finally
T.Free;
end;
finally
S.Free;
end;
End;
Time Stamp Compare Forensic
Whether you need to hide your recent activity on a computer or if you need to synchronize file dates, using this routine is the best way to adjust the creation, access, or modification dates and times of files or folders.
//The structure is as follows : (taken from Win32 Reference Guide)
(*typedef struct _WIN32_FIND_DATA { // wfd
DWORD dwFileAttributes;
FILETIME ftCreationTime;
FILETIME ftLastAccessTime;
FILETIME ftLastWriteTime;
DWORD nFileSizeHigh;
DWORD nFileSizeLow;
DWORD dwReserved0;
DWORD dwReserved1;
TCHAR cFileName[ MAX_PATH ];
TCHAR cAlternateFileName[ 14 ]; *)
//http://docwiki.embarcadero.com/Libraries/Sydney/en/System.SysUtils.TSearchRec
function FileGetSizeX(const DirBase, extension: string): Int64;
{$ifndef fpc}
var FileInfo: TSearchRec; srlist: TStringlist;
timestamp, createdate: Tdatetime; tcompare: integer;
{$endif}
begin
{$ifdef fpc}
Result:= FileUtil.FileSize(FileName);
{$else}
//from maXbox4FileUtil code
srlist:= FindAllFiles(DirBase,extension,true) //true:recursive
for it:= 0 to srlist.count-1 do begin
FileInfo.Name:= srlist.strings[it]; //filename;
FileInfo.FindHandle:= {Win.}FindFirstFile({Win.}
{LPTSTR}(FileInfo.Name),FileInfo.FindData);
if FileInfo.FindHandle={Win.}Invalid_Handle_value then
begin
Result:=-1;
Exit;
end;
Result:=(int64(FileInfo.FindData.nFileSizeHigh)
Shl 32)+ FileInfo.FindData.nFileSizeLow;
timestamp:=
FileTimeToDateTime(fileinfo.finddata.ftLastWriteTime);
createdate:=
FileTimeToDateTime(fileinfo.finddata.ftCreationTime);
tcompare:= CompareDateTime(timestamp, createdate)
{Win.}FindCloseW(FileInfo.FindHandle);
// FileDateToDateTime(fileinfo.time);
writeln(itoa(it+1)+ ': '+srlist.strings[it]+
' sz:'+inttostr64(result)+ ' dt:'+
datetostr(timestamp)+'
cr:'+datetostr(createdate)+':'+itoa(tcompare));
end;
srlist.Free;
{$endif}
end;
While programming file handling, especially changing file date and time, I
used the function FindFirst() to get the filehandle, in which one of the arguments is of type TSearchRec.
This component has the property FindData., of type TWin32FindData. Unfortunately, on-line help would not provide the properties of TWin32FindData, while using a watch on this component shows that there must be quite some properties as listed above.
Word Count Routine
Not so trivial but almost blameable. Knowing the word count of a text can be important. For example, if an author has to write a minimum or maximum amount of words for an article, essay, report, story, book, paper, you name it. A Routine will help to make sure its word count reaches a specific requirement or stays within a certain limit.
function WordCount3(const S:String; const WordDelims:TCharSet):
Integer;
var sLen, i: integer;
begin
Result:= 0; i:= 1;
sLen:= Length(S);
writeln('debug '+itoa(slen))
while i <= sLen-1 do begin
while (i <= sLen) and CharInSet(S[i],WordDelims) do Inc(i);
if i <= sLen then Inc(Result);
while not(i >=sLen) and Not isCharInSet(S[i],WordDelims) do
Inc(i);
end;
end;
In writing a story, recommended word counts only really come into play when you’re weighing up your publishing options. For example, literary magazines typically have strict limits to the length of short stories they will print. After all, they have a limited number of pages for each issue (and their editors only have so many hours in the week to edit manuscripts).

Model Appendix
model = ARIMA(differenced, order=(7,0,1))
model_fit = model.fit()
model_fit.summary()
“””
SARIMAX Results
Dep. Variable: y No. Observations: 3285
Model: ARIMA(7, 0, 1) Log Likelihood -8689.286
Date: Mon, 29 Mar 2021 AIC 17398.571
Time: 15:18:25 BIC 17459.542
Sample: 0 HQIC 17420.401
– 3285
Covariance Type: opg
coef std err z P>|z| [0.025 0.975]
const 0.0152 0.132 0.115 0.909 -0.244 0.275
ar.L1 1.1442 0.314 3.642 0.000 0.528 1.760
ar.L2 -0.4358 0.168 -2.594 0.009 -0.765 -0.106
ar.L3 0.0962 0.044 2.179 0.029 0.010 0.183
ar.L4 0.0126 0.029 0.427 0.669 -0.045 0.070
ar.L5 -0.0103 0.029 -0.362 0.717 -0.066 0.046
ar.L6 0.0124 0.026 0.485 0.628 -0.038 0.063
ar.L7 0.0086 0.025 0.345 0.730 -0.040 0.057
ma.L1 -0.6172 0.314 -1.967 0.049 -1.232 -0.002
sigma2 11.6150 0.281 41.386 0.000 11.065 12.165
===
Ljung-Box (Q): 50.56 Jarque-Bera (JB): 1.55
Prob(Q): 0.12 Prob(JB): 0.46
Heteroskedasticity (H): 0.84 Skew: -0.02
Prob(H) (two-sided): 0.00 Kurtosis: 3.10
===
model = ARIMA(series.Temp, order=(7,1,1))
model_fit = model.fit()
model_fit.summary()
“””
SARIMAX Results
Dep. Variable: Temp No. Observations: 3650
Model: ARIMA(7, 1, 1) Log Likelihood -8386.229
Date: Mon, 29 Mar 2021 AIC 16790.457
Time: 15:18:50 BIC 16846.277
Sample: 0 HQIC 16810.336
– 3650
Covariance Type: opg
coef std err z P>|z| [0.025 0.975]
ar.L1 0.4973 0.023 21.748 0.000 0.453 0.542
ar.L2 -0.1303 0.019 -6.752 0.000 -0.168 -0.092
ar.L3 0.0035 0.020 0.175 0.861 -0.036 0.043
ar.L4 -0.0037 0.020 -0.189 0.850 -0.042 0.035
ar.L5 0.0022 0.019 0.114 0.909 -0.035 0.040
ar.L6 -0.0056 0.018 -0.306 0.759 -0.042 0.030
ar.L7 0.0087 0.018 0.483 0.629 -0.027 0.044
ma.L1 -0.9016 0.017 -53.703 0.000 -0.935 -0.869
sigma2 5.8024 0.129 44.830 0.000 5.549 6.056
===
Ljung-Box (Q): 45.96 Jarque-Bera (JB): 14.26
Prob(Q): 0.24 Prob(JB): 0.00
Heteroskedasticity (H): 0.86 Skew: 0.08
Prob(H) (two-sided): 0.01 Kurtosis: 3.26
===
Warnings:
[1] Covariance matrix calculated using the outer product of gradients (complex-s
tep).
differenced = difference(X[:,1],180)
model = ARIMA(differenced, order=(7,0,1))
model_fit = model.fit()
model_fit.summary()
“””
SARIMAX Results
Dep. Variable: y No. Observations: 3470
Model: ARIMA(7, 0, 1) Log Likelihood -9136.165
Date: Mon, 29 Mar 2021 AIC 18292.331
Time: 15:37:28 BIC 18353.850
Sample: 0 HQIC 18314.296
– 3470
Covariance Type: opg
coef std err z P>|z| [0.025 0.975]
const -0.1465 1.761 -0.083 0.934 -3.598 3.305
ar.L1 1.4341 0.030 48.385 0.000 1.376 1.492
ar.L2 -0.5879 0.033 -17.669 0.000 -0.653 -0.523
ar.L3 0.1246 0.032 3.922 0.000 0.062 0.187
ar.L4 0.0078 0.031 0.253 0.801 -0.053 0.069
ar.L5 -0.0204 0.031 -0.662 0.508 -0.081 0.040
ar.L6 0.0311 0.029 1.063 0.288 -0.026 0.089
ar.L7 0.0057 0.020 0.285 0.775 -0.034 0.045
ma.L1 -0.8373 0.025 -33.309 0.000 -0.887 -0.788
sigma2 11.3278 0.265 42.797 0.000 10.809 11.847
===
Ljung-Box (Q): 76.34 Jarque-Bera (JB): 2.42
Prob(Q): 0.00 Prob(JB): 0.30
Heteroskedasticity (H): 0.90 Skew: -0.00
Prob(H) (two-sided): 0.08 Kurtosis: 3.13
===
differenced = difference(X[:,1],90)
model_fit = model.fit()
model = ARIMA(differenced, order=(7,0,1))
model_fit = model.fit()
model_fit.summary()
“””
SARIMAX Results
Dep. Variable: y No. Observations: 3560
Model: ARIMA(7, 0, 1) Log Likelihood -9402.551
Date: Mon, 29 Mar 2021 AIC 18825.102
Time: 15:41:35 BIC 18886.877
Sample: 0 HQIC 18847.130
– 3560
Covariance Type: opg
coef std err z P>|z| [0.025 0.975]
const -0.0568 1.112 -0.051 0.959 -2.235 2.122
ar.L1 1.4803 0.026 57.227 0.000 1.430 1.531
ar.L2 -0.6267 0.031 -19.976 0.000 -0.688 -0.565
ar.L3 0.1385 0.031 4.439 0.000 0.077 0.200
ar.L4 -0.0073 0.031 -0.233 0.816 -0.069 0.054
ar.L5 0.0131 0.031 0.419 0.676 -0.048 0.074
ar.L6 -0.0111 0.029 -0.386 0.699 -0.067 0.045
ar.L7 0.0074 0.018 0.403 0.687 -0.029 0.044
ma.L1 -0.8843 0.020 -43.684 0.000 -0.924 -0.845
sigma2 11.5186 0.271 42.474 0.000 10.987 12.050
===
Ljung-Box (Q): 56.31 Jarque-Bera (JB): 1.34
Prob(Q): 0.05 Prob(JB): 0.51
Heteroskedasticity (H): 0.84 Skew: -0.04
Prob(H) (two-sided): 0.00 Kurtosis: 3.06
===
new slides and libraries for it-sec:
<Words> ActnColorMaps, ActnCtrls, ActnList, ActnMan, ActnMenus, ActnPopup, ActnRes, ADOConst, ADODB, ADOInt, AppEvnts, AxCtrls, BandActn, bdeconst, bdemts, Buttons, CheckLst, Classes, Clipbrd.pas, CmAdmCtl, ComCtrls, ComStrs, Consts, Controls, CtlConsts, CtlPanel, CustomizeDlg, DataBkr, DB, DBActns, dbcgrids, DBClient, DBClientActnRes, DBClientActns, DBCommon, DBConnAdmin, DBConsts, DBCtrls, DbExcept, DBGrids, DBLocal, DBLocalI, DBLogDlg, dblookup, DBOleCtl, DBPWDlg, DBTables, DBXpress, DdeMan, Dialogs, DrTable, DSIntf, ExtActns, ExtCtrls, ExtDlgs, FileCtrl, FMTBcd, Forms, Graphics, GraphUtil, Grids, HTTPIntr, IB, IBBlob, IBCustomDataSet, IBDatabase, IBDatabaseInfo, IBDCLConst, IBErrorCodes, IBEvents, IBExternals, IBExtract, IBGeneratorEditor, IBHeader, IBIntf, IBQuery, IBRestoreEditor, IBSecurityEditor, IBServiceEditor, IBSQL, IBSQLMonitor, IBStoredProc, IBTable, IBUpdateSQL, IBUtils, IBXConst, ImgList, Jcl8087, JclAbstractContainers, JclAlgorithms, JclAnsiStrings, JclAppInst, JclArrayLists, JclArraySets, JclBase, JclBinaryTrees, JclBorlandTools, JclCIL, JclCLR, JclCOM, JclComplex, JclCompression, JclConsole, JclContainerIntf, JclCounter, JclDateTime, JclDebug, JclDotNet, JclEDI, JclEDI_ANSIX12, JclEDI_ANSIX12_Ext, JclEDI_UNEDIFACT, JclEDI_UNEDIFACT_Ext, JclEDISEF, JclEDITranslators, JclEDIXML, JclExprEval, JclFileUtils, JclFont, JclGraphics, JclGraphUtils, JclHashMaps, JclHashSets, JclHookExcept, JclIniFiles, JclLANMan, JclLinkedLists, JclLocales, JclLogic, JclMapi, JclMath, JclMetadata, JclMIDI, JclMime, JclMiscel, JclMsdosSys, JclMultimedia, JclNTFS, JclPCRE, JclPeImage, JclPrint, JclQGraphics, JclQGraphUtils, JclQueues, JclRegistry, JclResources, JclRTTI, JclSchedule, JclSecurity, JclShell, JclSimpleXml, JclStacks, JclStatistics, JclStreams, JclStrHashMap, JclStringLists, JclStrings, JclStructStorage, JclSvcCtrl, JclSynch, JclSysInfo, JclSysUtils, JclTask, JclTD32, JclUnicode, JclUnitConv, JclUnitVersioning, JclUnitVersioningProviders, JclValidation, JclVectors, JclWideFormat, JclWideStrings, JclWin32, JclWin32Ex, JclWinMIDI, ListActns, Mask, MConnect, Menus, Midas, MidasCon, MidConst, MPlayer, MtsRdm, Mxconsts, ObjBrkr, OleAuto, OleConst, OleCtnrs, OleCtrls, OleDB, OleServer, Outline, Printers, Provider, recerror, ScktCnst, ScktComp, ScktMain, SConnect, ShadowWnd, SimpleDS, SMINTF, SqlConst, SqlExpr, SqlTimSt, StdActnMenus, StdActns, StdCtrls, StdStyleActnCtrls, SvcMgr, SysUtils, TabNotBk, Tabs, TConnect, Themes, ToolWin, ValEdit, VDBConsts, WinHelpViewer, XPActnCtrls, XPMan, XPStyleActnCtrls </Words>
https://matplotlib.org/stable/tutorials/introductory/pyplot.html
Let’s bring out the seasonality a little bit by creating lag-plots of the the current average monthly temperature against time-lagged values of itself, for various months. Here are the lag-plots:

https://timeseriesreasoning.com/2019/11/16/how-to-select-a-regression-model-using-aic/
Regression goal
Our goal is to predict the average temperature in Boston for the current month.
Regression strategy
The strategy we will follow is as follows:
- We will build several Ordinary Least Square Regression (OLSR) models for the temperature data set.
- In each model, the response variable will be the current month’s average temperature. This is the TAVG column in the data set.
- In each model, the regression variables i.e. the explanatory variables will be different combinations of time lagged temperature variables.
- We will train each model on the temperature data set and we’ll select the model with the lowest AIC score.


The last IV










































http://www.herongyang.com/Bitcoin/Block-Data-Calculate-Double-SHA256-with-Python.html
LikeLiked by 1 person
a lot of snippets
https://levelup.gitconnected.com/22-python-code-snippets-for-everyday-problems-4c6a216c33ae
LikeLike