Commit 6ac0f8aa authored by rarnu's avatar rarnu

add: 大致完成了残局编辑器第一版

parent 3e682306
.idea/
.vscode/
.fleet/
*.o
*.ppu
### Mac OS ###
.DS_Store
## MDPro3
Data/
## binary
*.exe
## lazarus
backup/
*.lps
<?xml version="1.0" encoding="UTF-8"?>
<CONFIG>
<ProjectOptions>
<Version Value="12"/>
<PathDelim Value="\"/>
<General>
<SessionStorage Value="InProjectDir"/>
<Title Value="PuzzleEditor"/>
<Scaled Value="True"/>
<ResourceType Value="res"/>
<UseXPManifest Value="True"/>
<XPManifest>
<DpiAware Value="True"/>
</XPManifest>
<Icon Value="0"/>
</General>
<BuildModes>
<Item Name="Default" Default="True"/>
</BuildModes>
<PublishOptions>
<Version Value="2"/>
<UseFileFilters Value="True"/>
</PublishOptions>
<RunParams>
<FormatVersion Value="2"/>
</RunParams>
<RequiredPackages>
<Item>
<PackageName Value="pl_orca"/>
</Item>
<Item>
<PackageName Value="FCL"/>
</Item>
<Item>
<PackageName Value="SQLDBLaz"/>
</Item>
<Item>
<PackageName Value="LCL"/>
</Item>
</RequiredPackages>
<Units>
<Unit>
<Filename Value="PuzzleEditor.lpr"/>
<IsPartOfProject Value="True"/>
</Unit>
<Unit>
<Filename Value="untdata.pas"/>
<IsPartOfProject Value="True"/>
<UnitName Value="untData"/>
</Unit>
<Unit>
<Filename Value="frmhome.pas"/>
<IsPartOfProject Value="True"/>
<ComponentName Value="FormHome"/>
<HasResources Value="True"/>
<ResourceBaseClass Value="Form"/>
<UnitName Value="frmHome"/>
</Unit>
<Unit>
<Filename Value="untconstant.pas"/>
<IsPartOfProject Value="True"/>
<UnitName Value="untConstant"/>
</Unit>
<Unit>
<Filename Value="untcard.pas"/>
<IsPartOfProject Value="True"/>
<UnitName Value="untCard"/>
</Unit>
<Unit>
<Filename Value="untutils.pas"/>
<IsPartOfProject Value="True"/>
<UnitName Value="untUtils"/>
</Unit>
<Unit>
<Filename Value="frmsearchcard.pas"/>
<IsPartOfProject Value="True"/>
<ComponentName Value="FormSearchCard"/>
<HasResources Value="True"/>
<ResourceBaseClass Value="Form"/>
<UnitName Value="frmSearchCard"/>
</Unit>
<Unit>
<Filename Value="untlistitem.pas"/>
<IsPartOfProject Value="True"/>
<UnitName Value="untListItem"/>
</Unit>
<Unit>
<Filename Value="iscbase\ISCHttp.pas"/>
<IsPartOfProject Value="True"/>
</Unit>
<Unit>
<Filename Value="iscbase\ISCJSON.pas"/>
<IsPartOfProject Value="True"/>
</Unit>
<Unit>
<Filename Value="iscbase\ISCThread.pas"/>
<IsPartOfProject Value="True"/>
</Unit>
<Unit>
<Filename Value="iscbase\untimagedownloader.pas"/>
<IsPartOfProject Value="True"/>
<UnitName Value="untImageDownloader"/>
</Unit>
<Unit>
<Filename Value="frmcardlist.pas"/>
<IsPartOfProject Value="True"/>
<ComponentName Value="FormCardList"/>
<HasResources Value="True"/>
<ResourceBaseClass Value="Form"/>
<UnitName Value="frmCardList"/>
</Unit>
<Unit>
<Filename Value="untcardjson.pas"/>
<IsPartOfProject Value="True"/>
<UnitName Value="untCardJson"/>
</Unit>
<Unit>
<Filename Value="frmcontinouseffected.pas"/>
<IsPartOfProject Value="True"/>
<ComponentName Value="FormContinousEffected"/>
<HasResources Value="True"/>
<ResourceBaseClass Value="Form"/>
<UnitName Value="frmContinousEffected"/>
</Unit>
<Unit>
<Filename Value="frmpuzzleconfig.pas"/>
<IsPartOfProject Value="True"/>
<ComponentName Value="FormPuzzleConfig"/>
<HasResources Value="True"/>
<ResourceBaseClass Value="Form"/>
<UnitName Value="frmPuzzleConfig"/>
</Unit>
<Unit>
<Filename Value="untscriptgenerator.pas"/>
<IsPartOfProject Value="True"/>
<UnitName Value="untScriptGenerator"/>
</Unit>
<Unit>
<Filename Value="frmabout.pas"/>
<IsPartOfProject Value="True"/>
<ComponentName Value="FormAbout"/>
<HasResources Value="True"/>
<ResourceBaseClass Value="Form"/>
<UnitName Value="frmAbout"/>
</Unit>
</Units>
</ProjectOptions>
<CompilerOptions>
<Version Value="11"/>
<PathDelim Value="\"/>
<Target>
<Filename Value="PuzzleEditor"/>
</Target>
<SearchPaths>
<IncludeFiles Value="$(ProjOutDir)"/>
<OtherUnitFiles Value="iscbase"/>
<UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
</SearchPaths>
<Linking>
<Debugging>
<DebugInfoType Value="dsDwarf2"/>
</Debugging>
<Options>
<Win32>
<GraphicApplication Value="True"/>
</Win32>
</Options>
</Linking>
</CompilerOptions>
<Debugging>
<Exceptions>
<Item>
<Name Value="EAbort"/>
</Item>
<Item>
<Name Value="ECodetoolError"/>
</Item>
<Item>
<Name Value="EFOpenError"/>
</Item>
<Item>
<Name Value="EFileNotFoundException"/>
</Item>
<Item>
<Name Value="ESSLSocketError"/>
</Item>
<Item>
<Name Value="EInOutError"/>
</Item>
<Item>
<Name Value="RunError(5)"/>
</Item>
<Item>
<Name Value="RunError(103)"/>
</Item>
</Exceptions>
</Debugging>
</CONFIG>
program PuzzleEditor;
{$mode objfpc}{$H+}
uses
{$IFDEF UNIX}
cthreads,
{$ENDIF}
{$IFDEF HASAMIGA}
athreads,
{$ENDIF}
Interfaces, // this includes the LCL widgetset
Forms, opensslsockets, untData, frmHome;
{$R *.res}
begin
RequireDerivedFormResource:=True;
Application.Scaled:=True;
Application.Initialize;
Application.CreateForm(TFormHome, FormHome);
Application.Run;
end.
# puzzle-editor # 残局编辑器
残局编辑器
\ No newline at end of file
object FormAbout: TFormAbout
Left = 650
Height = 500
Top = 44
Width = 900
BorderIcons = [biSystemMenu]
BorderStyle = bsDialog
Caption = '关于'
ClientHeight = 500
ClientWidth = 900
DesignTimePPI = 192
Position = poMainFormCenter
object Scene: TD2Scene
Left = 0
Height = 500
Top = 0
Width = 900
Align = alClient
DesignSnapGridShow = False
DesignSnapToGrid = False
DesignSnapToLines = True
object Root1: TD2Background
Width = 900
Height = 500
HitTest = False
end
end
end
unit frmAbout;
{$mode ObjFPC}{$H+}
interface
uses
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, orca_scene2d;
type
{ TFormAbout }
TFormAbout = class(TForm)
Root1: TD2Background;
Scene: TD2Scene;
private
public
end;
var
FormAbout: TFormAbout;
implementation
{$R *.lfm}
end.
object FormCardList: TFormCardList
Left = 654
Height = 1200
Top = 44
Width = 900
BorderIcons = [biSystemMenu]
BorderStyle = bsDialog
Caption = '卡片列表'
ClientHeight = 1200
ClientWidth = 900
DesignTimePPI = 192
OnCreate = FormCreate
OnDestroy = FormDestroy
Position = poMainFormCenter
object Scene: TD2Scene
Left = 0
Height = 1200
Top = 0
Width = 900
Align = alClient
DesignSnapGridShow = False
DesignSnapToGrid = False
DesignSnapToLines = True
object Root: TD2Background
Width = 900
Height = 1200
Margins.Rect = '(16,16,16,16)'
HitTest = False
object Layout1: TD2Layout
Align = vaBottom
Position.Point = '(16,1104)'
Width = 868
Height = 80
object btnOK: TD2CornerButton
Align = vaRight
Position.Point = '(740,8)'
Width = 120
Height = 64
Padding.Rect = '(8,8,8,8)'
TabOrder = 0
StaysPressed = False
IsPressed = False
Font.Family = 'microsoft yahei'
Font.Size = 28
ModalResult = 1
TextAlign = d2TextAlignCenter
Text = '确定'
xRadius = 3
yRadius = 3
Sides = [d2SideTop, d2SideLeft, d2SideBottom, d2SideRight]
end
object btnCancel: TD2CornerButton
Align = vaRight
Position.Point = '(604,8)'
Width = 120
Height = 64
Padding.Rect = '(8,8,8,8)'
TabOrder = 1
StaysPressed = False
IsPressed = False
Font.Family = 'microsoft yahei'
Font.Size = 28
ModalResult = 2
TextAlign = d2TextAlignCenter
Text = '取消'
xRadius = 3
yRadius = 3
Sides = [d2SideTop, d2SideLeft, d2SideBottom, d2SideRight]
end
object btnAddCard: TD2CornerButton
Align = vaLeft
Position.Point = '(8,8)'
Width = 187
Height = 64
Padding.Rect = '(8,8,8,8)'
OnClick = btnAddCardClick
TabOrder = 2
StaysPressed = False
IsPressed = False
Font.Family = 'microsoft yahei'
Font.Size = 28
TextAlign = d2TextAlignCenter
Text = '添加卡片'
xRadius = 3
yRadius = 3
Sides = [d2SideTop, d2SideLeft, d2SideBottom, d2SideRight]
end
end
object lstCards: TD2ListBox
Align = vaClient
Position.Point = '(16,16)'
Width = 868
Height = 1088
TabOrder = 1
end
end
end
end
unit frmCardList;
{$mode Delphi}{$H+}
interface
uses
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, orca_scene2d, fgl, untData, untCard;
type
{ TFormCardList }
TFormCardList = class(TForm)
btnOK: TD2CornerButton;
btnCancel: TD2CornerButton;
btnAddCard: TD2CornerButton;
Layout1: TD2Layout;
lstCards: TD2ListBox;
Root: TD2Background;
Scene: TD2Scene;
procedure btnAddCardClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
FCardList: TFPGList<Int64>;
procedure deleteCardItem(ACardId: Int64; AIndex: Integer);
public
procedure FillCardIds(list: TFPGList<Int64>);
published
property CardList: TFPGList<Int64> read FCardList;
end;
var
FormCardList: TFormCardList;
implementation
uses untListItem, frmSearchCard;
{$R *.lfm}
{ TFormCardList }
procedure TFormCardList.btnAddCardClick(Sender: TObject);
var
cid: Int64 = 0;
item: TCardListItemOp;
begin
with TFormSearchCard.Create(Self) do begin
if ShowModal = mrOK then begin
cid := CardId;
end;
Free;
end;
if cid > 0 then begin
FCardList.Add(cid);
lstCards.BeginUpdate;
item := TCardListItemOp.Create(lstCards);
item.CardName:= Cards.GetCardName(cid);
item.Id:= cid;
item.ShowFace := False;
item.OnDelete:= deleteCardItem;
lstCards.EndUpdate;
end;
end;
procedure TFormCardList.FormCreate(Sender: TObject);
begin
FCardList := TFPGList<Int64>.Create;
end;
procedure TFormCardList.FormDestroy(Sender: TObject);
begin
FCardList.Free;
end;
procedure TFormCardList.deleteCardItem(ACardId: Int64; AIndex: Integer);
var
i: Integer;
begin
// index matches
if (FCardList[AIndex] = ACardId) then begin
FCardList.Delete(AIndex);
lstCards.Items[AIndex].Free;
Exit;
end;
// index not match
FCardList.Remove(ACardId);
for i := 0 to lstCards.Count - 1 do begin
if TCardListItemOp(lstCards.Items[i]).Id = ACardId then begin
lstCards.Items[i].Free;
Break;
end;
end;
end;
procedure TFormCardList.FillCardIds(list: TFPGList<Int64>);
var
i: Integer;
item: TCardListItemOp;
cn: string;
begin
FCardList.Clear;
FCardList.AddList(list);
lstCards.Clear;
if (list.Count > 0) then begin
lstCards.BeginUpdate;
for i:= 0 to FCardList.Count - 1 do begin
cn := Cards.GetCardName(FCardList[i]);
item := TCardListItemOp.Create(lstCards);
item.CardName:= cn;
item.Id:= FCardList[i];
item.ShowFace := False;
item.OnDelete:= deleteCardItem;
end;
lstCards.EndUpdate;
end;
end;
end.
object FormContinousEffected: TFormContinousEffected
Left = 650
Height = 1200
Top = 44
Width = 900
BorderIcons = [biSystemMenu]
BorderStyle = bsDialog
Caption = '永续受影响的卡片'
ClientHeight = 1200
ClientWidth = 900
DesignTimePPI = 192
OnCreate = FormCreate
OnDestroy = FormDestroy
Position = poMainFormCenter
LCLVersion = '3.6.0.0'
object Scene: TD2Scene
Left = 0
Height = 1200
Top = 0
Width = 900
Align = alClient
DesignSnapGridShow = False
DesignSnapToGrid = False
DesignSnapToLines = True
object Root: TD2Background
Width = 900
Height = 1200
Margins.Rect = '(16,16,16,16)'
HitTest = False
object Layout1: TD2Layout
Align = vaBottom
Position.Point = '(16,1104)'
Width = 868
Height = 80
object CornerButton1: TD2CornerButton
Align = vaRight
Position.Point = '(740,8)'
Width = 120
Height = 64
Padding.Rect = '(8,8,8,8)'
OnClick = CornerButton1Click
TabOrder = 0
StaysPressed = False
IsPressed = False
Font.Family = 'microsoft yahei'
Font.Size = 28
ModalResult = 1
TextAlign = d2TextAlignCenter
Text = '确定'
xRadius = 3
yRadius = 3
Sides = [d2SideTop, d2SideLeft, d2SideBottom, d2SideRight]
end
object CornerButton2: TD2CornerButton
Align = vaRight
Position.Point = '(604,8)'
Width = 120
Height = 64
Padding.Rect = '(8,8,8,8)'
TabOrder = 1
StaysPressed = False
IsPressed = False
Font.Family = 'microsoft yahei'
Font.Size = 28
ModalResult = 2
TextAlign = d2TextAlignCenter
Text = '取消'
xRadius = 3
yRadius = 3
Sides = [d2SideTop, d2SideLeft, d2SideBottom, d2SideRight]
end
end
object lstCards: TD2ListBox
Align = vaClient
Position.Point = '(16,16)'
Width = 868
Height = 1088
TabOrder = 1
end
end
end
end
unit frmContinousEffected;
{$mode Delphi}{$H+}
interface
uses
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, orca_scene2d, untCard, untListItem, fgl, untData;
type
{ TFormContinousEffected }
TFormContinousEffected = class(TForm)
CornerButton1: TD2CornerButton;
CornerButton2: TD2CornerButton;
Layout1: TD2Layout;
lstCards: TD2ListBox;
Root: TD2Background;
Scene: TD2Scene;
procedure CornerButton1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
FCESelectedCards: TFPGList<TCard>;
FCurrentCard: TCard;
FPuzzle: TPuzzleField;
public
procedure RefreshList();
published
// managed by FormHome
property CEPuzzle: TPuzzleField read FPuzzle write FPuzzle;
property CECurrentCard: TCard read FCurrentCard write FCurrentCard;
property CESelectedCards: TFPGList<TCard> read FCESelectedCards;
end;
var
FormContinousEffected: TFormContinousEffected;
implementation
uses
untUtils;
{$R *.lfm}
{ TFormContinousEffected }
procedure TFormContinousEffected.FormCreate(Sender: TObject);
begin
FCESelectedCards := TFPGList<TCard>.Create;
end;
procedure TFormContinousEffected.CornerButton1Click(Sender: TObject);
var
i: Integer;
item: TCardListItemCheck;
begin
FCESelectedCards.Clear;
for i := 0 to lstCards.Count - 1 do begin
item := TCardListItemCheck(lstCards.Items[i]);
if (item.Checked) then begin
FCESelectedCards.Add(item.Card);
end;
end;
end;
procedure TFormContinousEffected.FormDestroy(Sender: TObject);
begin
FCESelectedCards.Free;
// FreeCards(FCESelectedCards);
end;
procedure TFormContinousEffected.RefreshList();
var
i: Integer;
c: TCard;
item: TCardListItemCheck;
begin
if FPuzzle = nil then Exit;
if FCurrentCard = nil then Exit;
lstCards.Clear;
for i:= 0 to 4 do begin
c := FPuzzle.MCard[0, i];
if (c <> nil) then begin
item := TCardListItemCheck.Create(lstCards);
item.CardName:= c.CardName;
item.Id:= c.CardId;
item.Player:= 0;
item.Card := c;
item.Checked:= PickOneCardFromList(FCurrentCard.ContinousEffectTo, c.CardId, c.Owner, c.Player, c.Location, c.Seq) <> nil;
end;
end;
for i:= 0 to 5 do begin
c := FPuzzle.SCard[0, i];
if (c <> nil) then begin
item := TCardListItemCheck.Create(lstCards);
item.CardName:= c.CardName;
item.Id:= c.CardId;
item.Player:= 0;
item.Card := c;
item.Checked:= PickOneCardFromList(FCurrentCard.ContinousEffectTo, c.CardId, c.Owner, c.Player, c.Location, c.Seq) <> nil;
end;
end;
for i := 5 to 6 do begin
c := FPuzzle.ExtraMonster[i];
if (c <> nil) then begin
item := TCardListItemCheck.Create(lstCards);
item.CardName:= c.CardName;
item.Id:= c.CardId;
item.Player:= IfThen<Integer>(c.Owner = coSelf, 0, 1);
item.Card := c;
item.Checked:= PickOneCardFromList(FCurrentCard.ContinousEffectTo, c.CardId, c.Owner, c.Player, c.Location, c.Seq) <> nil;
end;
end;
for i := 1 to 4 do begin
c := FPuzzle.MCard[1, i];
if (c <> nil) then begin
item := TCardListItemCheck.Create(lstCards);
item.CardName:= c.CardName;
item.Id:= c.CardId;
item.Player:= 1;
item.Card := c;
item.Checked:= PickOneCardFromList(FCurrentCard.ContinousEffectTo, c.CardId, c.Owner, c.Player, c.Location, c.Seq) <> nil;
end;
end;
for i := 1 to 5 do begin
c := FPuzzle.SCard[1, i];
if (c <> nil) then begin
item := TCardListItemCheck.Create(lstCards);
item.CardName:= c.CardName;
item.Id:= c.CardId;
item.Player:= 1;
item.Card := c;
item.Checked:= PickOneCardFromList(FCurrentCard.ContinousEffectTo, c.CardId, c.Owner, c.Player, c.Location, c.Seq) <> nil;
end;
end;
end;
end.
This diff is collapsed.
This diff is collapsed.
object FormPuzzleConfig: TFormPuzzleConfig
Left = 650
Height = 1200
Top = 44
Width = 900
BorderIcons = [biSystemMenu]
BorderStyle = bsDialog
Caption = '残局设置'
ClientHeight = 1200
ClientWidth = 900
DesignTimePPI = 192
Position = poMainFormCenter
object Scene: TD2Scene
Left = 0
Height = 1200
Top = 0
Width = 900
Align = alClient
DesignSnapGridShow = False
DesignSnapToGrid = False
DesignSnapToLines = True
object Root: TD2Background
Width = 900
Height = 1200
Margins.Rect = '(16,16,16,16)'
HitTest = False
object Layout1: TD2Layout
Align = vaTop
Position.Point = '(16,16)'
Width = 868
Height = 80
object Label1: TD2Label
Align = vaLeft
Position.Point = '(8,0)'
Width = 180
Height = 80
Padding.Rect = '(8,0,0,0)'
TabOrder = 0
Font.Family = 'Microsoft yahei'
Font.Size = 24
Font.Style = d2FontBold
TextAlign = d2TextAlignNear
VertTextAlign = d2TextAlignCenter
Text = '己方生命值'
end
object edtSelfLP: TD2NumberBox
Align = vaClient
Position.Point = '(196,8)'
Width = 664
Height = 64
Padding.Rect = '(8,8,8,8)'
TabOrder = 1
Font.Family = 'Microsoft Yahei'
Font.Size = 24
ReadOnly = False
Max = 1000000
Value = 8000
ValueType = d2ValueInteger
HorzIncrement = 1
VertIncrement = 1
end
end
object Layout2: TD2Layout
Align = vaTop
Position.Point = '(16,96)'
Width = 868
Height = 80
object Label2: TD2Label
Align = vaLeft
Position.Point = '(8,0)'
Width = 180
Height = 80
Padding.Rect = '(8,0,0,0)'
TabOrder = 0
Font.Family = 'Microsoft yahei'
Font.Size = 24
Font.Style = d2FontBold
TextAlign = d2TextAlignNear
VertTextAlign = d2TextAlignCenter
Text = '对方生命值'
end
object edtOpponentLP: TD2NumberBox
Align = vaClient
Position.Point = '(196,8)'
Width = 664
Height = 64
Padding.Rect = '(8,8,8,8)'
TabOrder = 1
Font.Family = 'Microsoft Yahei'
Font.Size = 24
ReadOnly = False
Max = 1000000
Value = 8000
ValueType = d2ValueInteger
HorzIncrement = 1
VertIncrement = 1
end
end
object Layout3: TD2Layout
Align = vaTop
Position.Point = '(16,176)'
Width = 868
Height = 400
object Label3: TD2Label
Align = vaTop
Position.Point = '(8,0)'
Width = 860
Height = 80
Padding.Rect = '(8,0,0,0)'
TabOrder = 0
Font.Family = 'Microsoft yahei'
Font.Size = 24
Font.Style = d2FontBold
TextAlign = d2TextAlignNear
VertTextAlign = d2TextAlignCenter
Text = '残局描述'
end
object mmMessage: TD2Memo
Align = vaClient
Position.Point = '(8,88)'
Width = 852
Height = 304
Padding.Rect = '(8,8,8,8)'
TabOrder = 1
WordWrap = False
end
end
object Layout4: TD2Layout
Align = vaClient
Position.Point = '(16,576)'
Width = 868
Height = 528
object Label4: TD2Label
Align = vaTop
Position.Point = '(8,0)'
Width = 860
Height = 80
Padding.Rect = '(8,0,0,0)'
TabOrder = 0
Font.Family = 'Microsoft yahei'
Font.Size = 24
Font.Style = d2FontBold
TextAlign = d2TextAlignNear
VertTextAlign = d2TextAlignCenter
Text = '解决方案'
end
object mmSolution: TD2Memo
Align = vaClient
Position.Point = '(8,88)'
Width = 852
Height = 432
Padding.Rect = '(8,8,8,8)'
TabOrder = 1
WordWrap = False
end
end
object Layout5: TD2Layout
Align = vaBottom
Position.Point = '(16,1104)'
Width = 868
Height = 80
object CornerButton1: TD2CornerButton
Align = vaRight
Position.Point = '(740,8)'
Width = 120
Height = 64
Padding.Rect = '(8,8,8,8)'
TabOrder = 0
StaysPressed = False
IsPressed = False
Font.Family = 'microsoft yahei'
Font.Size = 28
ModalResult = 1
TextAlign = d2TextAlignCenter
Text = '确定'
xRadius = 3
yRadius = 3
Sides = [d2SideTop, d2SideLeft, d2SideBottom, d2SideRight]
end
object CornerButton2: TD2CornerButton
Align = vaRight
Position.Point = '(604,8)'
Width = 120
Height = 64
Padding.Rect = '(8,8,8,8)'
TabOrder = 1
StaysPressed = False
IsPressed = False
Font.Family = 'microsoft yahei'
Font.Size = 28
ModalResult = 2
TextAlign = d2TextAlignCenter
Text = '取消'
xRadius = 3
yRadius = 3
Sides = [d2SideTop, d2SideLeft, d2SideBottom, d2SideRight]
end
end
end
end
end
unit frmPuzzleConfig;
{$mode ObjFPC}{$H+}
interface
uses
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, orca_scene2d;
type
{ TFormPuzzleConfig }
TFormPuzzleConfig = class(TForm)
CornerButton1: TD2CornerButton;
CornerButton2: TD2CornerButton;
Label1: TD2Label;
Label2: TD2Label;
Label3: TD2Label;
Label4: TD2Label;
Layout1: TD2Layout;
Layout2: TD2Layout;
Layout3: TD2Layout;
Layout4: TD2Layout;
Layout5: TD2Layout;
edtSelfLP: TD2NumberBox;
edtOpponentLP: TD2NumberBox;
mmMessage: TD2Memo;
mmSolution: TD2Memo;
Root: TD2Background;
Scene: TD2Scene;
private
function GetP0LP: Integer;
function GetP1LP: Integer;
function GetPMessage: string;
function GetPSolution: string;
procedure SetP0LP(AValue: Integer);
procedure SetP1LP(AValue: Integer);
procedure SetPMessage(AValue: string);
procedure SetPSolution(AValue: string);
public
published
property P0LP: Integer read GetP0LP write SetP0LP;
property P1LP: Integer read GetP1LP write SetP1LP;
property PMessage: string read GetPMessage write SetPMessage;
property PSolution: string read GetPSolution write SetPSolution;
end;
var
FormPuzzleConfig: TFormPuzzleConfig;
implementation
{$R *.lfm}
{ TFormPuzzleConfig }
function TFormPuzzleConfig.GetP0LP: Integer;
begin
Exit(Trunc(edtSelfLP.Value));
end;
function TFormPuzzleConfig.GetP1LP: Integer;
begin
Exit(Trunc(edtOpponentLP.Value));
end;
function TFormPuzzleConfig.GetPMessage: string;
begin
Exit(mmMessage.Lines.Text);
end;
function TFormPuzzleConfig.GetPSolution: string;
begin
Exit(mmSolution.Lines.Text);
end;
procedure TFormPuzzleConfig.SetP0LP(AValue: Integer);
begin
edtSelfLP.Value:= AValue;
end;
procedure TFormPuzzleConfig.SetP1LP(AValue: Integer);
begin
edtOpponentLP.Value:= AValue;
end;
procedure TFormPuzzleConfig.SetPMessage(AValue: string);
begin
mmMessage.Lines.Text:= AValue;
end;
procedure TFormPuzzleConfig.SetPSolution(AValue: string);
begin
mmSolution.Lines.Text:= AValue;
end;
end.
object FormSearchCard: TFormSearchCard
Left = 654
Height = 1200
Top = 44
Width = 900
BorderIcons = [biSystemMenu]
BorderStyle = bsDialog
Caption = '卡片查询'
ClientHeight = 1200
ClientWidth = 900
DesignTimePPI = 192
Position = poMainFormCenter
LCLVersion = '3.6.0.0'
object Scene: TD2Scene
Left = 0
Height = 1200
Top = 0
Width = 900
Align = alClient
DesignSnapGridShow = False
DesignSnapToGrid = False
DesignSnapToLines = True
object Root: TD2Background
Width = 900
Height = 1200
Margins.Rect = '(16,16,16,16)'
HitTest = False
object Layout1: TD2Layout
Align = vaTop
Position.Point = '(16,16)'
Width = 868
Height = 80
object Label1: TD2Label
Align = vaLeft
Width = 120
Height = 80
TabOrder = 0
Font.Family = 'Microsoft yahei'
Font.Size = 24
Font.Style = d2FontBold
TextAlign = d2TextAlignCenter
VertTextAlign = d2TextAlignCenter
Text = '搜索卡名'
end
object edtCardName: TD2TextBoxClearBtn
Align = vaLeft
Position.Point = '(136,16)'
Width = 362
Height = 48
Padding.Rect = '(16,16,16,16)'
TabOrder = 1
Font.Family = 'microsoft yahei'
Font.Size = 28
ReadOnly = False
Password = False
Text = '魔术师'
end
object btnSearchCard: TD2CornerButton
Align = vaLeft
Position.Point = '(522,8)'
Width = 120
Height = 64
Padding.Rect = '(8,8,8,8)'
OnClick = btnSearchCardClick
TabOrder = 2
StaysPressed = False
IsPressed = False
Font.Family = 'microsoft yahei'
Font.Size = 28
TextAlign = d2TextAlignCenter
Text = '搜索'
xRadius = 3
yRadius = 3
Sides = [d2SideTop, d2SideLeft, d2SideBottom, d2SideRight]
end
end
object lstCards: TD2ListBox
Align = vaClient
Position.Point = '(16,96)'
Width = 868
Height = 992
OnClick = lstCardsClick
TabOrder = 2
Columns = 3
end
object Layout2: TD2Layout
Align = vaBottom
Position.Point = '(16,1104)'
Width = 868
Height = 80
Padding.Rect = '(0,16,0,0)'
object btnCancel: TD2CornerButton
Align = vaRight
Position.Point = '(604,8)'
Width = 120
Height = 64
Padding.Rect = '(8,8,8,8)'
TabOrder = 0
StaysPressed = False
IsPressed = False
Font.Family = 'microsoft yahei'
Font.Size = 28
ModalResult = 2
TextAlign = d2TextAlignCenter
Text = '取消'
xRadius = 3
yRadius = 3
Sides = [d2SideTop, d2SideLeft, d2SideBottom, d2SideRight]
end
object btnOK: TD2CornerButton
Align = vaRight
Enabled = False
Position.Point = '(740,8)'
Width = 120
Height = 64
Padding.Rect = '(8,8,8,8)'
OnClick = btnOKClick
TabOrder = 1
StaysPressed = False
IsPressed = False
Font.Family = 'microsoft yahei'
Font.Size = 28
TextAlign = d2TextAlignCenter
Text = '确定'
xRadius = 3
yRadius = 3
Sides = [d2SideTop, d2SideLeft, d2SideBottom, d2SideRight]
end
end
end
end
end
unit frmSearchCard;
{$mode Delphi}{$H+}
interface
uses
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, orca_scene2d, untData, untCard, fgl;
type
{ TFormSearchCard }
TFormSearchCard = class(TForm)
btnSearchCard: TD2CornerButton;
btnCancel: TD2CornerButton;
btnOK: TD2CornerButton;
Label1: TD2Label;
Layout1: TD2Layout;
Layout2: TD2Layout;
lstCards: TD2ListBox;
Root: TD2Background;
Scene: TD2Scene;
edtCardName: TD2TextBoxClearBtn;
procedure btnOKClick(Sender: TObject);
procedure btnSearchCardClick(Sender: TObject);
procedure lstCardsClick(Sender: TObject);
private
FCardId: Int64;
public
published
property CardId: Int64 read FCardId;
end;
var
FormSearchCard: TFormSearchCard;
implementation
uses
untListItem;
{$R *.lfm}
{ TFormSearchCard }
procedure TFormSearchCard.btnSearchCardClick(Sender: TObject);
var
keyword: string;
list: TFPGList<TCard>;
i: Integer;
item: TCardListItem;
begin
keyword:= edtCardName.Text;
if (keyword = '') then Exit;
list := Cards.SearchCards(keyword);
lstCards.Clear;
lstCards.BeginUpdate;
for i := 0 to list.Count - 1 do begin
item := TCardListItem.Create(lstCards);
item.CardName:= list[i].CardName;
item.Id:= list[i].CardId;
end;
lstCards.EndUpdate;
FreeCards(list);
btnOK.Enabled:= False;
// deselect all
lstCards.ItemIndex:= -1;
end;
procedure TFormSearchCard.lstCardsClick(Sender: TObject);
begin
btnOK.Enabled:= lstCards.ItemIndex > -1;
end;
procedure TFormSearchCard.btnOKClick(Sender: TObject);
begin
FCardId := TCardListItem(lstCards.Items[lstCards.ItemIndex]).Id;
self.ModalResult:= mrOK;
end;
end.
unit ISCConsts;
{$mode objfpc}{$H+}
{$ModeSwitch nestedprocvars}
interface
uses
Classes, SysUtils, fpwebfile, fphttpapp, ISCYaml;
const
SPL = {$IFDEF WINDOWS}'\'{$ELSE}'/'{$ENDIF};
type
TCustomConfigMethod = procedure (AYaml: TYamlFile);
var
MODULE_NAME: string = '';
SERVICE_NAME: string = '';
SERVER_PORT: Integer = 80;
QUEUE_SIZE: Integer = 1000;
ACTIVE_PROFILE: string = '';
WORK_DIR: string;
FILES_DIR: string;
CONFIG_DIR: string;
DATA_DIR: string;
TMP_DIR: string;
LOG_DIR: string;
LD_DIR: string;
BANNER_PATH: string;
APPLICATION_YML_PATH: string;
LOGGER_LEVEL: string = 'info';
procedure loadYamlConfig(cfg: TCustomConfigMethod = nil);
implementation
uses
ISCLogger;
procedure readYaml(y: TYamlFile; cfg: TCustomConfigMethod);
begin
MODULE_NAME:= y.GetValue('api-moudle', MODULE_NAME);
SERVER_PORT:= StrToIntDef(y.GetValue('server.port', SERVER_PORT.ToString), SERVER_PORT);
QUEUE_SIZE := StrToIntDef(y.GetValue('server.queue-size', QUEUE_SIZE.ToString), QUEUE_SIZE);
SERVICE_NAME:= y.GetValue('spring.application.name', SERVICE_NAME);
if (SERVICE_NAME = '') then begin
SERVICE_NAME:= y.GetValue('fpweb.application.name', SERVICE_NAME);
end;
LOGGER_LEVEL:= y.GetValue('logging.level.root', LOGGER_LEVEL);
if (cfg <> nil) then begin
cfg(y);
end;
end;
procedure preloadYaml(APath: string; cfg: TCustomConfigMethod);
var
y: TYamlFile;
begin
y := TYamlFile.Create();
y.LoadFromFile(APath);
ACTIVE_PROFILE := y.GetValue('spring.profiles.active', ACTIVE_PROFILE);
if (ACTIVE_PROFILE = '') then begin
ACTIVE_PROFILE:= y.GetValue('fpweb.profiles.active', ACTIVE_PROFILE);
end;
readYaml(y, cfg);
if(ACTIVE_PROFILE <> '') then begin
// override sub profile
if (FileExists(WORK_DIR + 'application-' + ACTIVE_PROFILE + '.yml')) then begin
APPLICATION_YML_PATH := WORK_DIR + 'application-' + ACTIVE_PROFILE + '.yml';
y.LoadFromFile(APPLICATION_YML_PATH);
readYaml(y, cfg);
end;
if (FileExists(CONFIG_DIR + 'application-' + ACTIVE_PROFILE + '.yml')) then begin
APPLICATION_YML_PATH := CONFIG_DIR + 'application-' + ACTIVE_PROFILE + '.yml';
y.LoadFromFile(APPLICATION_YML_PATH);
readYaml(y, cfg);
end;
end;
y.Free;
end;
procedure loadYamlConfig(cfg: TCustomConfigMethod);
begin
if (FileExists(WORK_DIR + 'application.yml')) then begin
APPLICATION_YML_PATH:= WORK_DIR + 'application.yml';
preloadYaml(APPLICATION_YML_PATH, cfg);
end;
if (FileExists(CONFIG_DIR + 'application.yml')) then begin
APPLICATION_YML_PATH:= CONFIG_DIR + 'application.yml';
preloadYaml(APPLICATION_YML_PATH, cfg);
end;
TLogger.info('main', 'MODULE_NAME = ' + MODULE_NAME);
TLogger.info('main', 'SERVICE_NAME = ' + SERVICE_NAME);
TLogger.info('main', 'SERVER_PORT = ' + SERVER_PORT.ToString);
TLogger.info('main', 'QUEUE_SIZE = ' + QUEUE_SIZE.ToString);
TLogger.info('main', 'ACTIVE_PROFILE = ' + ACTIVE_PROFILE);
end;
initialization
WORK_DIR := ExtractFilePath(Application.ExeName);
if (WORK_DIR.EndsWith('.' + SPL)) then begin
WORK_DIR := WORK_DIR.Substring(0, WORK_DIR.Length - 2);
end;
FILES_DIR := WORK_DIR + 'files' + SPL;
if (not DirectoryExists(FILES_DIR)) then begin
ForceDirectories(FILES_DIR);
end;
MimeTypesFile:= FILES_DIR + 'mime.txt';
RegisterFileLocation('static', {$IFDEF WINDOWS}'files'{$ELSE}FILES_DIR{$ENDIF});
// create tmp folder
TMP_DIR:= WORK_DIR + 'tmp' + SPL;
if (not DirectoryExists(TMP_DIR)) then begin
ForceDirectories(TMP_DIR);
end;
LOG_DIR := WORK_DIR + 'logs' + SPL;
if (not DirectoryExists(LOG_DIR)) then begin
ForceDirectories(LOG_DIR);
end;
LD_DIR:= WORK_DIR + 'ld' + SPL;
if (not DirectoryExists(LD_DIR)) then begin
ForceDirectories(LD_DIR);
end;
CONFIG_DIR:= WORK_DIR + 'config' + SPL;
if (not DirectoryExists(CONFIG_DIR)) then begin
ForceDirectories(CONFIG_DIR);
end;
DATA_DIR:= WORK_DIR + 'data' + SPL;
if (not DirectoryExists(DATA_DIR)) then begin
ForceDirectories(DATA_DIR);
end;
end.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
unit ISCJSON;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, fpjson, fpjsonrtti;
type
{ TISCJSONObject }
TISCJSONObject = class(TJSONObject)
private
function GetOptArrays(AName : String): TJSONArray;
function GetOptObjects(AName: string): TJSONObject;
public
function OptIntegers(AName: String; ADefault: Integer): Integer;
function OptInt64s(AName: string; ADefault: Int64): Int64;
function OptQWords(AName: string; ADefault: QWord): QWord;
function OptFloats(AName: string; ADefault: Double): Double;
function OptNulls(AName: string; ADefault: Boolean): Boolean;
function OptStrings(AName: string; ADefault: string): string;
function OptUnicodeStrings(AName: string; ADefault: UnicodeString): UnicodeString;
function OptBooleans(AName: string; ADefault: Boolean): Boolean;
Property OptArrays[AName : String] : TJSONArray Read GetOptArrays;
property OptObjects[AName: string]: TJSONObject read GetOptObjects;
end;
{ TISCJSONArray }
TISCJSONArray = class(TJSONArray)
private
function GetOptArrays(Index: Integer): TJSONArray;
function GetOptObjects(Index: Integer): TJSONObject;
public
function OptIntegers(Index: Integer; ADefault: Integer): Integer;
function OptInt64s(Index: Integer; ADefault: Int64): Int64;
function OptStrings(Index: Integer; ADefault: string): string;
function OptQWords(Index: Integer; ADefault: QWord): QWord;
function OptNulls(Index: Integer; ADefault: Boolean): Boolean;
function OptUnicodeStrings(Index: Integer; ADefault: UnicodeString): UnicodeString;
function OptFloats(Index: Integer; ADefault: Double): Double;
function OptBooleans(Index: Integer; ADefault: Boolean): Boolean;
property OptArrays[Index: Integer]: TJSONArray read GetOptArrays;
property OptObjects[Index: Integer]: TJSONObject read GetOptObjects;
end;
generic function ISCObjectToJSONString<T: TObject>(AObj: T): string;
generic function ISCObjectToJSONObject<T: TObject>(AObj: T): TJSONObject;
generic function ISCJSONStringToObject<T: TObject>(jsonstr: string): T;
generic function ISCJSONObjectToObject<T: TObject>(AJson: TJSONObject): T;
implementation
generic function ISCObjectToJSONString<T>(AObj: T): string;
var
js: TJSONStreamer;
begin
js := TJSONStreamer.Create(nil);
js.Options:= [jsoTStringsAsArray];
Result := js.ObjectToJSONString(AObj);
js.Free;
end;
generic function ISCObjectToJSONObject<T>(AObj: T): TJSONObject;
var
js: TJSONStreamer;
begin
js := TJSONStreamer.Create(nil);
js.Options:= [jsoTStringsAsArray];
Result := js.ObjectToJSON(AObj);
js.Free;
end;
generic function ISCJSONStringToObject<T>(jsonstr: string): T;
var
ret: T = nil;
js: TJSONDeStreamer;
begin
ret := T.Create;
js := TJSONDeStreamer.Create(nil);
js.Options:= [jdoCaseInsensitive,jdoIgnorePropertyErrors];
js.JSONToObject(jsonstr, ret);
js.Free;
Exit(ret);
end;
generic function ISCJSONObjectToObject<T>(AJson: TJSONObject): T;
var
ret: T = nil;
js: TJSONDeStreamer;
begin
ret := T.Create;
js := TJSONDeStreamer.Create(nil);
js.Options:= [jdoCaseInsensitive,jdoIgnorePropertyErrors];
js.JSONToObject(AJson, ret);
js.Free;
Exit(ret);
end;
{ TISCJSONArray }
function TISCJSONArray.GetOptArrays(Index: Integer): TJSONArray;
var
ret: TJSONArray = nil;
begin
try
ret := Self.Arrays[Index];
except
ret := nil;
end;
Exit(ret);
end;
function TISCJSONArray.GetOptObjects(Index: Integer): TJSONObject;
var
ret: TJSONObject = nil;
begin
try
ret := Self.Objects[Index];
except
ret := nil;
end;
Exit(ret);
end;
function TISCJSONArray.OptIntegers(Index: Integer; ADefault: Integer): Integer;
var
ret: Integer;
begin
try
ret := Self.Integers[Index];
except
ret := ADefault;
end;
Exit(ret);
end;
function TISCJSONArray.OptInt64s(Index: Integer; ADefault: Int64): Int64;
var
ret: Int64;
begin
try
ret := Self.Int64s[Index];
except
ret := ADefault;
end;
Exit(ret);
end;
function TISCJSONArray.OptStrings(Index: Integer; ADefault: string): string;
var
ret: string;
begin
try
ret := Self.Strings[Index];
except
ret := ADefault;
end;
Exit(ret);
end;
function TISCJSONArray.OptQWords(Index: Integer; ADefault: QWord): QWord;
var
ret: QWord;
begin
try
ret := Self.QWords[Index];
except
ret := ADefault;
end;
Exit(ret);
end;
function TISCJSONArray.OptNulls(Index: Integer; ADefault: Boolean): Boolean;
var
ret: Boolean;
begin
try
ret := Self.Nulls[Index];
except
ret := ADefault;
end;
Exit(ret);
end;
function TISCJSONArray.OptUnicodeStrings(Index: Integer; ADefault: UnicodeString
): UnicodeString;
var
ret: UnicodeString;
begin
try
ret := Self.UnicodeStrings[Index];
except
ret := ADefault;
end;
Exit(ret);
end;
function TISCJSONArray.OptFloats(Index: Integer; ADefault: Double): Double;
var
ret: Double;
begin
try
ret := Self.Floats[Index];
except
ret := ADefault;
end;
Exit(ret);
end;
function TISCJSONArray.OptBooleans(Index: Integer; ADefault: Boolean): Boolean;
var
ret: Boolean;
begin
try
ret := Self.Booleans[Index];
except
ret := ADefault;
end;
Exit(ret);
end;
{ TISCJSONObject }
function TISCJSONObject.GetOptArrays(AName : String): TJSONArray;
var
arr: TJSONArray = nil;
begin
try
arr := Self.Arrays[AName];
finally
end;
Exit(arr);
end;
function TISCJSONObject.GetOptObjects(AName: string): TJSONObject;
var
obj: TJSONObject = nil;
begin
try
obj := Self.Objects[AName];
finally
end;
Exit(obj);
end;
function TISCJSONObject.OptIntegers(AName: String; ADefault: Integer): Integer;
var
ret: Integer;
begin
try
ret:= Self.Integers[AName];
except
ret := ADefault;
end;
Exit(ret);
end;
function TISCJSONObject.OptInt64s(AName: string; ADefault: Int64): Int64;
var
ret: Int64;
begin
try
ret:= Self.Int64s[AName];
except
ret := ADefault;
end;
Exit(ret);
end;
function TISCJSONObject.OptQWords(AName: string; ADefault: QWord): QWord;
var
ret: QWord;
begin
try
ret:= Self.QWords[AName];
except
ret := ADefault;
end;
Exit(ret);
end;
function TISCJSONObject.OptFloats(AName: string; ADefault: Double): Double;
var
ret: Double;
begin
try
ret:= Self.Floats[AName];
except
ret := ADefault;
end;
Exit(ret);
end;
function TISCJSONObject.OptNulls(AName: string; ADefault: Boolean): Boolean;
var
ret: Boolean;
begin
try
ret:= Self.Nulls[AName];
except
ret := ADefault;
end;
Exit(ret);
end;
function TISCJSONObject.OptStrings(AName: string; ADefault: string): string;
var
ret: string;
begin
try
ret:= Self.Strings[AName];
except
ret := ADefault;
end;
Exit(ret);
end;
function TISCJSONObject.OptUnicodeStrings(AName: string; ADefault: UnicodeString
): UnicodeString;
var
ret: UnicodeString;
begin
try
ret:= Self.UnicodeStrings[AName];
except
ret := ADefault;
end;
Exit(ret);
end;
function TISCJSONObject.OptBooleans(AName: string; ADefault: Boolean): Boolean;
var
ret: Boolean;
begin
try
ret:= Self.Booleans[AName];
except
ret := ADefault;
end;
Exit(ret);
end;
end.
unit ISCLogger;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils;
type
{ TLogger }
TLogger = class
public
class procedure info(AModule: string; AMsg: string);
class procedure debug(AModule: string; AMsg: string);
class procedure warn(AModule: string; AMsg: string);
class procedure error(AModule: string; AMsg: string);
end;
implementation
uses
ISCConsts;
type
TLogType = (ltInfo, ltDebug, ltWarn, ltError);
function logTypeToStr(ALv: TLogType): string;
begin
case ALv of
ltInfo: Result := 'INFO';
ltDebug: Result := 'DEBUG';
ltWarn: Result:= 'WARN';
ltError: Result := 'ERROR';
end;
end;
procedure innerWriteLog(AModule: string; AMsg: string; ALevel: TLogType);
var
log: TextFile;
filePath: string;
logText: string;
colorText: string;
begin
if (LOGGER_LEVEL = 'error') and (not (ALevel in [ltError])) then Exit;
if (LOGGER_LEVEL = 'warn') and (not (ALevel in [ltWarn, ltError])) then Exit;
if (LOGGER_LEVEL = 'info') and (not (ALevel in [ltInfo, ltWarn, ltError])) then Exit;
filePath:= LOG_DIR;
case ALevel of
ltInfo: filePath += 'app-info.log';
ltDebug: filePath += 'app-debug.log';
ltWarn: filePath += 'app-warn.log';
ltError: filePath += 'app-error.log';
end;
filePath += '.' + FormatDateTime('yyyyMMdd', Now);
AssignFile(log, filePath);
if (FileExists(filePath)) then begin
Append(log);
end else begin
Rewrite(log);
end;
logText:= '[%s][%s] %s %s'.Format([FormatDateTime('yyyy-MM-dd hh:mm:ss', Now), AModule, logTypeToStr(ALevel), AMsg]);
// CRT
case ALevel of
ltError: colorText:= #27'[31m' + logText + #27'[0m';
ltWarn: colorText:= #27'[33m' + logText + #27'[0m';
ltInfo: colorText:= logText;
ltDebug: colorText:= #27'[32m' + logText + #27'[0m';
end;
// WriteLn(colorText);
// log file
WriteLn(log, logText);
Flush(log);
CloseFile(log);
end;
class procedure TLogger.info(AModule: string; AMsg: string);
begin
innerWriteLog(AModule, AMsg, ltInfo);
end;
class procedure TLogger.debug(AModule: string; AMsg: string);
begin
innerWriteLog(AModule, AMsg, ltDebug);
end;
class procedure TLogger.warn(AModule: string; AMsg: string);
begin
innerWriteLog(AModule, AMsg, ltWarn);
end;
class procedure TLogger.error(AModule: string; AMsg: string);
begin
innerWriteLog(AModule, AMsg, ltError);
end;
end.
unit ISCStringUtil;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, base64, md5, DateUtils, RegExpr, sha1;
function base64Eecode(str: string): string;
function base64Decode(str: string): string;
function md5Encode(str: string): string;
function sha1Encode(str: string): string;
function TimeStampToReadableDate(t: Int64): string;
function StrToJSONEncoded(AStr: string): string;
function characterToHalf(str: string): string;
function numberToHalf(str: string): string;
function toDBC(str: string): string;
function StringReplaceRegEx(const AStr: string; const ARegEx: string; AReplacement: string): string;
function StringReplaceRegEx(const AStr: string; const ARegEx: TRegExpr; AReplacement: string): string;
implementation
uses
ISCUTF8Helper;
type
{ TReplaceObj }
TReplaceObj = class
private
FReplacement: string;
public
constructor Create(ARep: string = '');
function Replace(r: TRegExpr): RegExprString;
function ReplaceStr(r: TRegExpr): RegExprString;
end;
{ TReplaceObj }
constructor TReplaceObj.Create(ARep: string);
begin
FReplacement:= ARep;
end;
function TReplaceObj.Replace(r: TRegExpr): RegExprString;
var
s: string;
begin
s := r.Match[0];
s := numberToHalf(s);
Exit(s);
end;
function TReplaceObj.ReplaceStr(r: TRegExpr): RegExprString;
begin
Exit(FReplacement);
end;
function StringReplaceRegEx(const AStr: string;const ARegEx: string; AReplacement: string): string;
var
reg: TRegExpr;
ro: TReplaceObj;
ret: string;
begin
reg:= TRegExpr.Create(ARegEx);
ro := TReplaceObj.Create(AReplacement);
ret := reg.Replace(AStr, @ro.ReplaceStr);
ro.Free;
reg.Free;
Exit(ret);
end;
function StringReplaceRegEx(const AStr: string;const ARegEx: TRegExpr; AReplacement: string): string;
var
ro: TReplaceObj;
ret: string;
begin
ro := TReplaceObj.Create(AReplacement);
ret := ARegEx.Replace(AStr, @ro.ReplaceStr);
ro.Free;
Exit(ret);
end;
function toDBC(str: string): string;
var
s: string;
begin
s := characterToHalf(str);
s := numberToHalf(s);
Exit(s);
end;
function characterToHalf(str: string): string;
var
len: Integer;
i: Integer;
c: Integer;
s: WideChar;
ret: string = '';
r: TRegExpr;
ro: TReplaceObj;
begin
len := str.ULength;
for i := 1 to len do begin
s := str.UChar[i];
c := s.UCode;
if (s = ' ') then begin
ret += ' ';
end else if (s = '﹒') then begin
ret += '·';
end else if (((s = '@') or (s = '.') or (s = '&') or (s = '?') or (s = '!')) or ((c >= 65313) and (c <= 65338)) or ((c >= 65338) and (c <= 65370))) then begin
ret += Char(c - 65248);
end else begin
ret += s.UAnsi;
end;
end;
ro := TReplaceObj.Create;
r := TRegExpr.Create('「.*?」');
ret := r.Replace(ret, @ro.Replace);
r.Free;
ro.Free;
Exit(ret);
end;
function numberToHalf(str: string): string;
var
len: Integer;
i: Integer;
ret: string = '';
s: WideChar;
c: Integer;
begin
len := str.ULength;
for i := 1 to len do begin
s := str.UChar[i];
c := s.UCode;
if (c >= 65296) and (c <= 65305) then begin
ret += Char(c - 65248);
end else begin
ret += s.UAnsi;
end;
end;
Exit(ret);
end;
function StrToJSONEncoded(AStr: string): string;
begin
Exit(AStr
.UReplace('"', '\"', [rfIgnoreCase, rfReplaceAll])
.UReplace(#13#10, '\n', [rfReplaceAll, rfIgnoreCase])
.UReplace(#10, '\n', [rfIgnoreCase, rfReplaceAll])
.UReplace(#13, '\n', [rfIgnoreCase, rfReplaceAll])
);
end;
function base64Eecode(str: string): string;
begin
Exit(EncodeStringBase64(str));
end;
function base64Decode(str: string): string;
begin
Exit(DecodeStringBase64(str));
end;
function md5Encode(str: string): string;
begin
Exit(MD5Print(MD5String(str)));
end;
function sha1Encode(str: string): string;
begin
Exit(SHA1Print(SHA1String(str)));
end;
function TimeStampToReadableDate(t: Int64): string;
var
dt: TDateTime;
begin
if (t = 0) then Exit('');
dt := UnixToDateTime(t, False);
Exit(FormatDateTime('yyyy-MM-dd hh:mm:ss', dt));
end;
end.
unit ISCThread;
{$mode objfpc}{$H+}
{$ModeSwitch nestedprocvars}
interface
uses
Classes, SysUtils;
type
generic TISCThreadMethod<D, T> = function (ATID: TThreadID; AData: D): T;
generic TISCNestedThreadMethod<D, T> = function (ATID: TThreadID; AData: D): T is nested;
generic TISCTerminateMethod<T> = procedure (ATID: TThreadID; AData: T);
generic TISCNestedTerminateMethod<T> = procedure (ATID: TThreadID; AData: T) is nested;
generic TISCThreadMethodGUI<D, T> = function (ATID: TThreadID; AData: D): T of object;
generic TISCTerminateMethodGUI<T> = procedure (ATID: TThreadID; AData: T) of object;
{ TInnerThread }
generic TInnerThread<D, T> = class(TThread)
private
FData: D;
FOutData: T;
FExecMethod: specialize TISCThreadMethod<D, T>;
FOutMethod: specialize TISCTerminateMethod<T>;
protected
procedure Execute; override;
public
constructor Create(InnerData: D; AMethod: specialize TISCThreadMethod<D, T>; ATermMethod: specialize TISCTerminateMethod<T>);
end;
{ TInnerNestedThread }
generic TInnerNestedThread<D, T> = class(TThread)
private
FData: D;
FOutData: T;
FExecMethod: specialize TISCNestedThreadMethod<D, T>;
FOutMethod: specialize TISCNestedTerminateMethod<T>;
protected
procedure Execute; override;
public
constructor Create(InnerData: D; AMethod: specialize TISCNestedThreadMethod<D, T>; ATermMethod: specialize TISCNestedTerminateMethod<T>);
end;
{ TInnerThreadGUI }
generic TInnerThreadGUI<D, T> = class(TThread)
private
FData: D;
FOutData: T;
FExecMethod: specialize TISCThreadMethodGUI<D, T>;
FOutMethod: specialize TISCTerminateMethodGUI<T>;
procedure innerTerminate(Sender: TObject);
protected
procedure Execute; override;
public
constructor Create(InnerData: D; AMethod: specialize TISCThreadMethodGUI<D, T>; ATermMethod: specialize TISCTerminateMethodGUI<T>);
end;
{ ISCThreadExecute for Non-GUI operating, "OnTerminate" callbacks in SUB-THREAD }
generic function ISCThreadExecute<E, U>(AData: E; AMethod: specialize TISCThreadMethod<E, U>; AOnTerminate: specialize TISCTerminateMethod<U> = nil; APriority: TThreadPriority = tpNormal): TThread;
{ ISCThreadExecute for Non-GUI-Nested operating, "OnTerminate" callbacks in Nested-SUB-THREAD }
generic function ISCThreadExecute<E, U>(AData: E; AMethod: specialize TISCNestedThreadMethod<E, U>; AOnTerminate: specialize TISCNestedTerminateMethod<U> = nil; APriority: TThreadPriority = tpNormal): TThread;
{ ISCThreadExecuteGUI for GUI operating, "OnTerminate" callbacks in UI-THREAD }
generic function ISCThreadExecuteGUI<E, U>(AData: E; AMethod: specialize TISCThreadMethodGUI<E, U>; AOnTerminate: specialize TISCTerminateMethodGUI<U> = nil; APriority: TThreadPriority = tpNormal): TThread;
implementation
{ TInnerNestedThread }
procedure TInnerNestedThread.Execute;
begin
FOutData:= FExecMethod(ThreadID, FData);
if (Assigned(FOutMethod)) then begin
FOutMethod(ThreadID, FOutData);
end;
Self.Free;
end;
constructor TInnerNestedThread.Create(InnerData: D; AMethod: specialize TISCNestedThreadMethod<D, T>; ATermMethod: specialize TISCNestedTerminateMethod<T>);
begin
inherited Create(True);
FData:= InnerData;
FExecMethod:= AMethod;
FOutMethod:= ATermMethod;
end;
{ TInnerThreadGUI }
procedure TInnerThreadGUI.innerTerminate(Sender: TObject);
begin
if (Assigned(FOutMethod)) then begin
FOutMethod(ThreadID, FOutData);
end;
end;
procedure TInnerThreadGUI.Execute;
begin
FOutData:= FExecMethod(ThreadID, FData);
end;
constructor TInnerThreadGUI.Create(InnerData: D; AMethod: specialize
TISCThreadMethodGUI<D, T>; ATermMethod: specialize TISCTerminateMethodGUI<T>);
begin
inherited Create(True);
FreeOnTerminate:= True;
OnTerminate:= @innerTerminate;
FData:= InnerData;
FExecMethod:= AMethod;
FOutMethod:= ATermMethod;
end;
{ TInnerThread }
procedure TInnerThread.Execute;
begin
FOutData := FExecMethod(ThreadID, FData);
if (Assigned(FOutMethod)) then begin
FOutMethod(ThreadID, FOutData);
end;
Self.Free;
end;
constructor TInnerThread.Create(InnerData: D;
AMethod: specialize TISCThreadMethod<D, T>; ATermMethod: specialize TISCTerminateMethod<T>);
begin
inherited Create(True);
FData:= InnerData;
FExecMethod:= AMethod;
FOutMethod:= ATermMethod;
end;
generic function ISCThreadExecute<E, U>(AData: E; AMethod: specialize TISCThreadMethod<E, U>; AOnTerminate: specialize TISCTerminateMethod<U>; APriority: TThreadPriority): TThread;
var
th: specialize TInnerThread<E, U>;
begin
th := specialize TInnerThread<E, U>.Create(AData, AMethod, AOnTerminate);
th.Priority := APriority;
th.Start();
Exit(th);
end;
generic function ISCThreadExecute<E, U>(AData: E; AMethod: specialize TISCNestedThreadMethod<E, U>; AOnTerminate: specialize TISCNestedTerminateMethod<U> = nil; APriority: TThreadPriority = tpNormal): TThread;
var
th: specialize TInnerNestedThread<E, U>;
begin
th := specialize TInnerNestedThread<E, U>.Create(AData, AMethod, AOnTerminate);
th.Priority:= APriority;
th.Start;
Exit(th);
end;
generic function ISCThreadExecuteGUI<E, U>(AData: E; AMethod: specialize TISCThreadMethodGUI<E, U>; AOnTerminate: specialize TISCTerminateMethodGUI<U>; APriority: TThreadPriority): TThread;
var
th: specialize TInnerThreadGUI<E, U>;
begin
th := specialize TInnerThreadGUI<E, U>.Create(AData, AMEthod, AOnTerminate);
th.Priority := APriority;
th.Start();
Exit(th);
end;
end.
This diff is collapsed.
unit ISCYaml;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, fgl, json2yaml;
type
{ TYamlFile }
TYamlFile = class
private
FList: TStringList;
public
constructor Create();
destructor Destroy; override;
procedure LoadFromFile(AFilePath: string);
procedure LoadFromStream(AStream: TStream);
procedure LoadString(AString: string);
function GetValue(APath: string; ADefault: string = ''): string;
function GetArrayValue(APath: string): TStringArray;
end;
implementation
{ TYamlFile }
constructor TYamlFile.Create();
begin
FList := TStringList.Create;
end;
destructor TYamlFile.Destroy;
begin
FList.Free;
inherited Destroy;
end;
procedure TYamlFile.LoadFromFile(AFilePath: string);
begin
FList.LoadFromFile(AFilePath);
end;
procedure TYamlFile.LoadFromStream(AStream: TStream);
begin
FList.LoadFromStream(AStream);
end;
procedure TYamlFile.LoadString(AString: string);
begin
FList.Text:= AString;
end;
function TYamlFile.GetValue(APath: string; ADefault: string): string;
var
i: Integer;
ret: string = '';
blocks: array of string;
lv: Integer = 0;
spcs: string;
begin
blocks := APath.Split(['.']);
for i := 0 to FList.Count - 1 do begin
spcs:= ''.PadRight(lv * 2);
if (FList[i].StartsWith(spcs + blocks[lv] + ':')) then begin
// hit key
if (lv = Length(blocks) - 1) then begin
ret := FList[i].Substring(FList[i].IndexOf(':') + 1).Trim;
Exit(ret);
end;
Inc(lv);
end;
end;
ret := ADefault;
Exit(ret);
end;
function TYamlFile.GetArrayValue(APath: string): TStringArray;
var
i: Integer;
j: Integer;
blocks: array of String;
spcs: string;
lv: Integer = 0;
ret: TStringArray = nil;
len: Integer = 0;
begin
blocks := APath.Split(['.']);
for i := 0 to FList.Count - 1 do begin
spcs:= ''.PadRight(lv * 2);
if (FList[i].StartsWith(spcs + blocks[lv] + ':')) then begin
// hit key
if (lv = Length(blocks) - 1) then begin
for j:= i + 1 to FList.Count - 1 do begin
if (FList[j].StartsWith(spcs + '- ')) then begin
Inc(len);
SetLength(ret, len);
ret[len - 1] := FList[j].Replace(spcs + '- ', '').Trim;
Continue;
end;
Break;
end;
Break;
end;
Inc(lv);
end;
end;
Exit(ret);
end;
end.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
{@********************************************************}
{ Copyright (c) 1999-2012 Zeos Development Group }
{ }
{ License Agreement: }
{ }
{ This library 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 Lesser General }
{ Public License for more details. }
{ }
{ The source code of the ZEOS Libraries and packages are }
{ distributed under the Library GNU General Public }
{ License (see the file COPYING / COPYING.ZEOS) }
{ with the following modification: }
{ As a special exception, the copyright holders of this }
{ library give you permission to link this library with }
{ independent modules to produce an executable, }
{ regardless of the license terms of these independent }
{ modules, and to copy and distribute the resulting }
{ executable under terms of your choice, provided that }
{ you also meet, for each linked independent module, }
{ the terms and conditions of the license of that module. }
{ An independent module is a module which is not derived }
{ from or based on this library. If you modify this }
{ library, you may extend this exception to your version }
{ of the library, but you are not obligated to do so. }
{ If you do not wish to do so, delete this exception }
{ statement from your version. }
{ }
{ }
{ The project web site is located on: }
{ http://zeos.firmos.at (FORUM) }
{ http://sourceforge.net/p/zeoslib/tickets/ (BUGTRACKER)}
{ svn://svn.code.sf.net/p/zeoslib/code-0/trunk (SVN) }
{ }
{ http://www.sourceforge.net/projects/zeoslib. }
{ }
{ }
{ Zeos Development Group. }
{********************************************************@}
{$IFDEF LINUX}
{$DEFINE UNIX}
{$ENDIF}
{$IFNDEF UNIX}
{$I ..\Zeos.inc}
{$ELSE}
{$I ../Zeos.inc}
{$ENDIF}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment