Good New Year's Day everyone! In this article, I would like to tell you how I had to return to a legacy project in Pascal, and literally before saying goodbye to him, to lazarus, and to the absence of a dark theme out of the box .
Last time I explained that I am not a programmer by profession, but I use my favorite hobby to automate everything that comes to hand in the work of a lawyer. I am sure that 90% of all legal red tape can be successfully automated: maintaining a variety of databases and cards, drawing up documents according to templates, controlling the timing of tasks, using any auxiliary services that already have their own api to screw automation at a specific workplace, etc. etc. It is necessary to strive for this in order, according to the behests of Isaac Asimov, to free up the time of a lawyer for the implementation of the main task - to reflect on the terms of the contract and breed demagoguery in court.
So, many years ago I did a very large project to make my office work easier. He collected all the data on trademarks and patents (and there are several hundred of them), controlled the timing of payment of patent fees, formed payment orders, contracts, applications, and, of course, issued various reports. Actually, why in the past tense? The project is quite working. It was just developed according to all possible anti-patterns, with all the bicycles and crutches that were only found on Earth. To return to this Rolton (or doshirak) code in order to refactor it, oh, I didn't want to, because the meme " Let's rewrite everything in ... " is perfect here .
But, unfortunately, rewriting everything anew in a new language for a new platform or even several is a long and protracted business, and documents need to be stamped here and now. Therefore, I have to return to Pascal from time to time.
One of the beautiful days, the whole project was rebuilt on a 64-bit platform, and, to my surprise, the most favorite part fell: the generation of contracts and statements with full automation of all grammar and morphology - the declension of initials, positions and other words in the necessary cases, and See also singular / plural. The thing is that the old Delphic and proprietary padegUC library has ceased to be free in its 64-bit version.
32- , . .
- , . , :
IInitialsMorpher = interface
function GetInitials(Initials: string): CasesResponse;
function GetWordsCase(Words: string): CasesResponse;
function GetGenderAndInitials(Initials: string; var Gender: TGender): CasesResponse;
end;
, , -: (.. ), , , , , , .. CasesResponse , Gender - :
TWordCase = (Nominative, Gentitive, Dative, Accusative, Instrumental, Prepositional);
TGender = (Male, Female, UnrecognizedGender);
CasesResponse = array[TWordCase] of string;
. , :
, Morphos, / .
rest api, json, , http, :
generic function JSONfromRestUri<T>(Uri: string): T;
var
HTTPSender: THTTPSend;
JSONStreamer: TJSONDeStreamer;
Json: TJSONObject;
begin
HTTPSender := THTTPSend.Create;
JSONStreamer := TJSONDeStreamer.Create(nil);
HTTPSender.Clear;
Result := T.Create;
if not HTTPSender.HTTPMethod('GET', Uri) then
raise EInOutError.Create(RESTOUT_ERROR);
JSON := GetJSON(HTTPSender.Document) as TJSONObject;
JSONStreamer.JSONToObject(JSON, Result);
FreeAndNil(JSON);
FreeAndNil(JSONStreamer);
FreeAndNil(HTTPSender);
end;
Freepascal Synapse Fpjson, (httpsend, fpjson, fpjsonrtti) uses. json rtti, .. , -, published, -, (, , ), -, json. , @SerializedName , .
Morphos :
MORPHOS_URL = 'http://morphos.io/api/inflect-name?name=%s&_format=json';
json , - / , , name gender:
{
"name": " ",
"cases": [
" ",
" ",
" ",
" ",
" ",
" "
],
"gender": "m"
}
IInitialsMorpher Morpher. , json Fpjson ( , TPersistent):
TMorphosResponse = class(TPersistent)
private
fCases: TStrings;
fGender: string;
fName: string;
public
constructor Create;
destructor Destroy; override;
published
property name: string read fName write fName;
property cases: TStrings read fCases write fCases;
property gender: string read fGender write fGender;
end;
:
TMorphosImpl = class(TInterfacedObject, IInitialsMorpher)
public
function GetInitials (Initials: string): CasesResponse;
function GetWordsCase (Words: string): CasesResponse;
function GetGenderAndInitials(Initials: string; var Gender: TGender): CasesResponse;
end;
, :
function TMorphosImpl.GetGenderAndInitials(Initials: string; var Gender: TGender): CasesResponse;
var
inf: TWordCase;
i: integer = 0;
response: TMorphosResponse;
begin
response := specialize JSONfromRestUri<TMorphosResponse>
(Replacetext(Format(MORPHOS_URL, [Initials]), ' ', '+'));
for inf in TWordCase do begin
Result[inf] := response.cases[i];
inc(i);
end;
case response.gender of
'm': Gender := Male;
'f': Gender := Female;
else Gender := UnrecognizedGender;
end;
FreeAndNil(response);
end;
, . , ( ) , , - :
function TMorphosImpl.GetInitials(Initials: string): CasesResponse;
var
MokeGender: TGender = UnrecognizedGender;
begin
Result := GetGenderAndInitials(Initials, MokeGender);
end;
function TMorphosImpl.GetWordsCase(Words: string): CasesResponse;
var
inf: TWordCase;
begin
Result := GetInitials(Words);
for inf in TWordCase do
Result[inf] := UTF8LowerString(Result[inf]);
end;
- -, ( , , - ?) - http-. Morphos , DaData , 10 .
, . , json ashMap- Generics.Collections - , freepascal delphi. , - ( , http- , ).
Morphos :
Morpher := TMorphFabric.Create(MORPHOS);
//...
response := Morpher.GetInitials(Text)
StringList.AddStrings(response);
For everyone interested, I will keep my resulting library with a test window application for win in an open repository . Most likely, I will not begin anything in it, because now I have plunged into the open sea of ββmobile development (kotlin) and python to implement the very same "rewrite everything in ..."
Happy New Year 2020 + '1' everyone!