433 lines
13 KiB
ObjectPascal
433 lines
13 KiB
ObjectPascal
{
|
|
********************************************************************************
|
|
|
|
YaPeTaVi - Yet another Periodic Table Viewer
|
|
Copyright (C) 1997-2000, 2009 Geoffray Levasseur <geoffray.levasseurbrandin@numericable.fr>.
|
|
All rights reserved.
|
|
http://www.geoffray-levasseur.org/
|
|
|
|
This program is free software; you can redistribute it and/or modify it under
|
|
the terms of the GNU General Public License as published by the Free Software
|
|
Foundation; either version 3 of the License, or (at your option) any later
|
|
version.
|
|
|
|
This program is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
|
PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License along with
|
|
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
|
Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
********************************************************************************
|
|
|
|
Description:
|
|
Mass calculator form unit
|
|
|
|
}
|
|
{$warning frmMassCalculator: change french strings in english resourcestring}
|
|
unit frmMassCalculator;
|
|
|
|
{$mode objfpc}{$H+}
|
|
interface
|
|
|
|
uses
|
|
{Windows,} SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls,
|
|
ComCtrls, ExtCtrls, Menus, LResources, Buttons, uConst, uElemListClass,
|
|
uCommon;
|
|
|
|
type
|
|
|
|
{ TMassCalcForm }
|
|
|
|
TMassCalcForm = class(TForm)
|
|
btnGo: TBitBtn;
|
|
btnClear: TBitBtn;
|
|
btnSave: TBitBtn;
|
|
btnClose: TBitBtn;
|
|
Edit: TEdit;
|
|
Memo: TMemo;
|
|
Panel1: TPanel;
|
|
Label1: TLabel;
|
|
Label2: TLabel;
|
|
Label3: TLabel;
|
|
Label4: TLabel;
|
|
Label5: TLabel;
|
|
Label6: TLabel;
|
|
Label7: TLabel;
|
|
Label8: TLabel;
|
|
Label9: TLabel;
|
|
Label10: TLabel;
|
|
Label11: TLabel;
|
|
Bevel1: TBevel;
|
|
Timer1: TTimer;
|
|
SaveDialog: TSaveDialog;
|
|
Label12: TLabel;
|
|
procedure FormCreate(Sender: TObject);
|
|
procedure btnCloseClick(Sender: TObject);
|
|
procedure btnGoClick(Sender: TObject);
|
|
procedure btnClearClick(Sender: TObject);
|
|
procedure Timer1Timer(Sender: TObject);
|
|
procedure EditChange(Sender: TObject);
|
|
procedure EditKeyPress(Sender: TObject; var Key: Char);
|
|
procedure btnSaveClick(Sender: TObject);
|
|
private
|
|
procedure Analyse(Elm: TElement);
|
|
procedure Decompose;
|
|
procedure ChError;
|
|
{ Déclarations privées }
|
|
public
|
|
{ Déclarations publiques }
|
|
end;
|
|
|
|
var
|
|
Entry: String;
|
|
Rep, G, St, X: Byte;
|
|
IsTested : Array[1..ElemNumber] of Boolean;
|
|
Result : Real;
|
|
Stat: Boolean;
|
|
MassCalcForm: TMassCalcForm;
|
|
|
|
implementation
|
|
|
|
uses
|
|
uIconManager;
|
|
|
|
procedure TMassCalcForm.FormCreate(Sender: TObject);
|
|
begin
|
|
{Initialise l'affichage de l'aide dans la barre d'état}
|
|
// Application.OnHint := ShowHint(Application);
|
|
{Au début le boutton Démarrage doit être désactivé}
|
|
InitBtnGlyphs(Self);
|
|
btnGo.Enabled := False;
|
|
{Charge les paramètres du registres}
|
|
end;
|
|
|
|
procedure TMassCalcForm.ChError;
|
|
begin
|
|
{Indication d'érreur}
|
|
Memo.Lines.Add(' -- Erreur au caractère ' + IntToStr(Rep));
|
|
end;
|
|
|
|
procedure TMassCalcForm.Analyse(Elm: TElement);
|
|
var
|
|
Inc: Boolean;
|
|
begin
|
|
Inc := Length(Trim(Elm.ShortName)) > 1;
|
|
{Détecte si l'élément est déjà présent}
|
|
if IsTested[Elm.Number] then
|
|
Memo.Lines.Add(' L''élément ' + Elm.Name +
|
|
' a déja été incorporé ! Simplifiez votre formule...');
|
|
{Ajout de l'élément dans le tableau des élément déjà analysé}
|
|
IsTested[Elm.Number] := True;
|
|
{Une lettre : on n'incrémente pas. Deux lettre : on incrémente}
|
|
if Inc then Rep := Rep + 1;
|
|
{Un élément différent des autres de plus}
|
|
G := G + 1;
|
|
{Stocke la masse molaire}
|
|
Elem[G].Typ := Elm.Number;
|
|
{Détection des chiffres - volontairement limité à 2}
|
|
if Entry[Rep + 1] in ['1'..'9'] then
|
|
begin
|
|
Rep := Rep + 1;
|
|
if entry[Rep + 1] in ['0'..'9'] then
|
|
begin
|
|
Elem[G].Num := ((Ord(Entry[Rep]) - 48) * 10) + (Ord(Entry[Rep + 1]) - 48);
|
|
Rep := Rep + 1;
|
|
end else
|
|
Elem[G].Num := Ord(Entry[Rep]) - 48;
|
|
end else Elem[G].Num := 1;
|
|
{Affiche les caractèristique de l'élément}
|
|
if ElementsList.Elements[Elem[G].Typ].Radioactivity <> '' then
|
|
Memo.Lines.Add(' ' + IntToStr(Elem[G].Num) + ' ' +
|
|
ElementsList.Elements[Elem[G].Typ].Name + ' / Masse Molaire pour un : ' +
|
|
FloatToStr(ElementsList.Elements[Elem[G].Typ].Mass) + ', soit : ' +
|
|
FloatToStr(Elem[G].Num * ElementsList.Elements[Elem[G].Typ].Mass) +
|
|
' (Artificial et/or radioactive!)')
|
|
else
|
|
Memo.Lines.Add(' ' + IntToStr(Elem[G].Num) + ' ' +
|
|
ElementsList.Elements[Elem[G].Typ].Name + ' / Masse Molaire pour un : ' +
|
|
FloatToStr(ElementsList.Elements[Elem[G].Typ].Mass) + ', soit : ' +
|
|
FloatToStr(Elem[G].Num * ElementsList.Elements[Elem[G].Typ].Mass));
|
|
{Met à jour le resultat}
|
|
Result := Result + (Elem[G].Num * ElementsList.Elements[Elem[G].Typ].Mass);
|
|
{Incrémente le compteur du nombre d'éléments}
|
|
X := X + Elem[G].Num;
|
|
end;
|
|
|
|
procedure TMassCalcForm.Decompose;
|
|
var L, J: Byte;
|
|
begin
|
|
{Initialisation}
|
|
if Memo.Lines.Count <> 0 then
|
|
Memo.Lines.Add('');
|
|
Memo.Lines.Add('Analysing the string "' + Edit.Text + '"...');
|
|
for J := 1 to
|
|
ElemNumber do IsTested[J] := False;
|
|
Entry := Edit.Text + #255; //facility to find the end of the string
|
|
St := 0;
|
|
Stat := True;
|
|
Result := 0;
|
|
G := 0;
|
|
X := 0;
|
|
Rep := 0;
|
|
L := Length(Entry);
|
|
//analysing char by char using case system (this have been writen a while ago
|
|
//so rewriting this with more efficiency, more possibility and less code would
|
|
//be great XD)
|
|
{$warning rewritind the awful and outdated TMassCalcForm.Decompose}
|
|
For Rep := 1 to L do
|
|
begin
|
|
case Entry[Rep] of
|
|
'A' : Case Entry[Rep+1] of
|
|
'l' : Analyse(Al);
|
|
's' : Analyse(Ars);
|
|
'g' : Analyse(Ag);
|
|
'u' : Analyse(Au);
|
|
't' : Analyse(At);
|
|
'c' : Analyse(Ac);
|
|
'm' : Analyse(Am);
|
|
'r' : Analyse(Ar);
|
|
else ChError
|
|
end;
|
|
'B' : if Entry[Rep+1] in ['a'..'z'] then
|
|
begin
|
|
case Entry[Rep+1] of
|
|
'r' : Analyse(Br);
|
|
'i' : Analyse(Bi);
|
|
'k' : Analyse(Bk);
|
|
'e' : Analyse(Be);
|
|
'a' : Analyse(Ba);
|
|
'h' : Analyse(Bh);
|
|
else Cherror
|
|
end;
|
|
end else Analyse(B);
|
|
'C' : if Entry[Rep+1] in ['a'..'z'] then
|
|
begin
|
|
case Entry[Rep+1] of
|
|
'l' : Analyse(Cl);
|
|
'o' : Analyse(Co);
|
|
'u' : Analyse(Cu);
|
|
's' : Analyse(Cs);
|
|
'a' : Analyse(Ca);
|
|
'r' : Analyse(Cr);
|
|
'd' : Analyse(Cd);
|
|
'e' : Analyse(Ce);
|
|
'm' : Analyse(Cm);
|
|
'f' : Analyse(Cf);
|
|
else Cherror
|
|
end;
|
|
end else Analyse(C);
|
|
'D' : case Entry[Rep+1] of
|
|
'y' : Analyse(Dy);
|
|
'b' : Analyse(Db);
|
|
's' : Analyse(Ds);
|
|
else ChError;
|
|
end;
|
|
'E' : case Entry[Rep+1] of
|
|
'u' : Analyse(Eu);
|
|
'r' : Analyse(Er);
|
|
's' : Analyse(Es);
|
|
else Cherror
|
|
end;
|
|
'F' : if Entry[Rep+1] in ['a'..'z'] then
|
|
begin
|
|
case Entry[Rep+1] of
|
|
'e' : Analyse(Fe);
|
|
'r' : Analyse(Fr);
|
|
'm' : Analyse(Fm);
|
|
else Cherror
|
|
end;
|
|
end else Analyse(F);
|
|
'G' : case Entry[Rep+1] of
|
|
'a' : Analyse(Ga);
|
|
'e' : Analyse(Ge);
|
|
'd' : Analyse(Gd);
|
|
else Cherror
|
|
end;
|
|
'H' : if Entry[Rep+1] in ['a'..'z'] then
|
|
begin
|
|
case Entry[Rep+1] of
|
|
'e' : Analyse(He);
|
|
'o' : Analyse(Ho);
|
|
'f' : Analyse(Hf);
|
|
'g' : Analyse(Hg);
|
|
's' : Analyse(Hs);
|
|
else Cherror
|
|
end;
|
|
end else Analyse(H);
|
|
'I' : if Entry[Rep+1] in ['a'..'z'] then
|
|
begin
|
|
case Entry[Rep+1] of
|
|
'n' : Analyse(Ind);
|
|
'r' : Analyse(Ir);
|
|
else Cherror
|
|
end;
|
|
end else Analyse(I);
|
|
'K' : if Entry[Rep+1]='r' then
|
|
Analyse(Kr)
|
|
else Analyse(K);
|
|
'L' : case Entry[Rep+1] of
|
|
'i' : Analyse(Li);
|
|
'a' : Analyse(La);
|
|
'r' : Analyse(Lr);
|
|
'u' : Analyse(Lu);
|
|
else Cherror
|
|
end;
|
|
'M' : case Entry[Rep+1] of
|
|
'g' : Analyse(Mg);
|
|
'n' : Analyse(Mn);
|
|
'o' : Analyse(Mo);
|
|
'd' : Analyse(Md);
|
|
't' : Analyse(Mt);
|
|
else Cherror
|
|
end;
|
|
'N' : if Entry[Rep+1] in ['a'..'z'] then
|
|
begin
|
|
case Entry[Rep+1] of
|
|
'e' : Analyse(Ne);
|
|
'a' : Analyse(Na);
|
|
'i' : Analyse(Ni);
|
|
'b' : Analyse(Nb);
|
|
'd' : Analyse(Nd);
|
|
'p' : Analyse(Np);
|
|
'o' : Analyse(No);
|
|
else Cherror
|
|
end;
|
|
end else Analyse(N);
|
|
'O' : if Entry[Rep+1]='s' then
|
|
Analyse(Os)
|
|
else
|
|
Analyse(O);
|
|
'P' : if Entry[Rep+1] in ['a'..'z'] then
|
|
begin
|
|
case Entry[Rep+1] of
|
|
'd' : Analyse(Pd);
|
|
'r' : Analyse(Pr);
|
|
'm' : Analyse(Pm);
|
|
't' : Analyse(Pt);
|
|
'b' : Analyse(Pb);
|
|
'o' : Analyse(Po);
|
|
'a' : Analyse(Pa);
|
|
'u' : Analyse(Pu);
|
|
else Cherror
|
|
end;
|
|
end else Analyse(P);
|
|
'R' : case Entry[Rep+1] of
|
|
'b' : Analyse(Rb);
|
|
'u' : Analyse(Ru);
|
|
'h' : Analyse(Rh);
|
|
'e' : Analyse(Re);
|
|
'n' : Analyse(Rn);
|
|
'a' : Analyse(Re);
|
|
'f' : Analyse(Rf);
|
|
'g' : Analyse(Rg);
|
|
else Cherror
|
|
end;
|
|
'S' : if Entry[Rep+1] in ['a'..'z'] then
|
|
begin
|
|
case Entry[Rep+1] of
|
|
'b' : Analyse(Sb);
|
|
'c' : Analyse(Sc);
|
|
'e' : Analyse(Se);
|
|
'g' : Analyse(Sg);
|
|
'i' : Analyse(Si);
|
|
'm' : Analyse(Sm);
|
|
'n' : Analyse(Sn);
|
|
'r' : Analyse(Sr);
|
|
else Cherror
|
|
end;
|
|
end else Analyse(S);
|
|
'T' : case Entry[Rep+1] of
|
|
'a' : Analyse(Ta);
|
|
'b' : Analyse(Tb);
|
|
'c' : Analyse(Tc);
|
|
'e' : Analyse(Te);
|
|
'h' : Analyse(Th);
|
|
'i' : Analyse(Ti);
|
|
'l' : Analyse(Tl);
|
|
'm' : Analyse(Tm);
|
|
else Cherror
|
|
end;
|
|
'U' : Analyse(U);
|
|
'V' : Analyse(V);
|
|
'W' : Analyse(W);
|
|
'X' : If Entry[Rep+1] = 'e' then
|
|
Analyse(Xe) else ChError;
|
|
'Y' : Analyse(Y);
|
|
'Z' : case Entry[Rep+1] of
|
|
'n' : Analyse(Zn);
|
|
'r' : Analyse(Zr);
|
|
else Cherror
|
|
end;
|
|
{Le caractère 255 est ajouté à l'initialisation et permet la detection
|
|
de la fin de la chaîne}
|
|
#255 : exit;
|
|
else ChError;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TMassCalcForm.btnCloseClick(Sender: TObject);
|
|
begin
|
|
Close;
|
|
Free;
|
|
MassCalcForm := nil;
|
|
end;
|
|
|
|
procedure TMassCalcForm.btnGoClick(Sender: TObject);
|
|
begin
|
|
{Lance la grosse artillerie...}
|
|
Decompose;
|
|
{Affichage des statistique et du résultat}
|
|
Memo.Lines.Add('A total of ' + IntToStr(G) + ' differents items have been found.');
|
|
Memo.Lines.Add('A total of ' + IntToStr(X) + ' atoms have been found.');
|
|
Memo.Lines.Add('Résultat final : ' + FloatToStr(Result));
|
|
Label11.Caption := FloatToStr(Result);
|
|
end;
|
|
|
|
procedure TMassCalcForm.btnClearClick(Sender: TObject);
|
|
begin
|
|
{Réinitialise l'affichage de la console et de la ligne d'édition}
|
|
Memo.Clear;
|
|
Edit.Clear;
|
|
end;
|
|
|
|
procedure TMassCalcForm.Timer1Timer(Sender: TObject);
|
|
begin
|
|
{Fait clignoter un texte Noir/Rouge}
|
|
if Label8.Font.Color = clRed then
|
|
Label8.Font.Color := clNone
|
|
else Label8.Font.Color := clRed;
|
|
end;
|
|
|
|
procedure TMassCalcForm.EditChange(Sender: TObject);
|
|
begin
|
|
{Interdit l'utilisation du boutton démarrage quand Edit est vide}
|
|
btnGo.Enabled := Edit.Text<>'';
|
|
end;
|
|
|
|
procedure TMassCalcForm.EditKeyPress(Sender: TObject; var Key: Char);
|
|
begin
|
|
{Gestion de la touche Entrée}
|
|
If (Key = #13) and (Edit.Text <> '') then
|
|
btnGoClick(Self);
|
|
end;
|
|
|
|
procedure TMassCalcForm.btnSaveClick(Sender: TObject);
|
|
begin
|
|
{Sauvegarde du contenu de la console}
|
|
if SaveDialog.Execute then
|
|
begin
|
|
if FileExists(SaveDialog.FileName) then
|
|
if MessageDlg('Are you sure you want to overwrite '+ SaveDialog.FileName
|
|
+ '?', mtConfirmation, mbYesNoCancel, 0) <> DR_YES then Exit;
|
|
Memo.Lines.SaveToFile(SaveDialog.FileName);
|
|
end;
|
|
end;
|
|
|
|
initialization
|
|
{$i frmmasscalculator.lrs}
|
|
|
|
end.
|