unit iBlogForm;
interface
uses
  Classes, SysUtils, IWAppForm, IWApplication, IWColor, IWTypes, IWCompMemo,
  IWCompLabel, IWIPhoneList, IWIPhoneMenu, IWIPhoneHeader, Controls, Forms,
  IWVCLBaseContainer, IWContainer, IWHTMLContainer, IWHTML40Container, IWRegion,
  IWIPhoneRegion, IWControl, IWIPhoneStyle, IWVCLBaseControl, IWBaseControl,
  IWBaseHTMLControl, IWIPhonePageFlip,
  ServerController, IWCompText, IWIPhoneScrollRegion, DB,
  ADODB, IWIPhoneButton, IWCompButton;

type
  TIWForm1 = class(TIWAppForm)
    TIWIPhonePageFlip1: TTIWIPhonePageFlip;
    TIWIPhoneStyle1: TTIWIPhoneStyle;
    TIWIPhoneRegion1: TTIWIPhoneRegion;
    TIWIPhoneRegion2: TTIWIPhoneRegion;
    TIWIPhoneHeader1: TTIWIPhoneHeader;
    TIWIPhoneHeader2: TTIWIPhoneHeader;
    TIWIPhoneList1: TTIWIPhoneList;
    IWLabel1: TIWLabel;
    IWLabel2: TIWLabel;
    TIWIPhoneMenu1: TTIWIPhoneMenu;
    TIWIPhoneRegion3: TTIWIPhoneRegion;
    TIWIPhoneHeader3: TTIWIPhoneHeader;
    TIWIPhoneList2: TTIWIPhoneList;
    TIWIPhoneRegion4: TTIWIPhoneRegion;
    TIWIPhoneHeader4: TTIWIPhoneHeader;
    ADOConnection1: TADOConnection;
    Query: TADOQuery;
    TIWIPhoneScrollRegion1: TTIWIPhoneScrollRegion;
    IWText1: TIWText;
    TIWIPhoneButton10: TTIWIPhoneButton;
    btn8: TIWButton;
    btn3: TIWButton;
    btn4: TIWButton;
    btn9: TIWButton;
    btn5: TIWButton;
    btn1: TIWButton;
    btn2: TIWButton;
    btn7: TIWButton;
    btn6: TIWButton;
    procedure IWAppFormCreate(Sender: TObject);
    procedure TIWIPhoneHeader2AsyncLeftButtonClick(Sender: TObject;
      EventParams: TStringList);
    procedure TIWIPhoneList1AsyncItemClick(Sender: TObject;
      EventParams: TStringList; ItemIndex: Integer);
    procedure TIWIPhoneHeader1LeftButtonClick(Sender: TObject);
    procedure TIWIPhoneMenu1ItemClick(Sender: TComponent; ItemIndex: Integer);
    procedure TIWIPhoneHeader3LeftButtonClick(Sender: TObject);
    procedure TIWIPhoneList2AsyncItemClick(Sender: TObject;
      EventParams: TStringList; ItemIndex: Integer);
    procedure TIWIPhoneHeaderRightButtonClick(Sender: TObject);
    procedure AsyncButtonClick(Sender: TObject;
      EventParams: TStringList);
    procedure TIWIPhoneButton10AsyncButtonClick(Sender: TObject;
      EventParams: TStringList);
  public
    const
      NoneID = 0;
      UserID = 1;
      CompID = 2;
      PlusID = 3;

    type
      TPlayer = NoneID..CompID;

    const
      cm_LeftUp      = 108;    { 8 3 4 }
      cm_LeftMiddle  = 101;    { 1 5 9 }
      cm_LeftDown    = 106;    { 6 7 2 }

      cm_MidUp       = 103;
      cm_MidMiddle   = 105;
      cm_MidDown     = 107;

      cm_RightUp     = 104;
      cm_RightMiddle = 109;
      cm_RightDown   = 102;

    const
      FirstPlace = 1;
      LastPlace  = 9;

    type
      TPlace = FirstPlace-1..LastPlace;

    type
      TBoard = Array[TPlace] of TPlayer;

    var
      Board: TBoard; { shared data space for each caller }

    function WinMove(ID: TPlayer): TPlace;
    function GetValue(Place: TPlace): TPlayer; export;
    function IsWinner: TPlayer; export;
    procedure MakeMove(ID: TPlayer; Place: TPlace); export;
    function NextMove(ID: TPlayer): TPlace; export;
  public
    CategoryID: Integer;
  private
    function ProcessContents(const Str: String): String;
  end;

var
  IWForm1: TIWForm1 = nil;

implementation

{$R *.dfm}

function TIWForm1.ProcessContents(const Str: String): String;
var
  i,j: Integer;
begin
  Result := Str;
  while (Pos(' http://',Result) > 0) or (Pos(#10'http://',Result) > 0) do
  begin
    i := Pos(' http://',Result) + 1;
    if i = 1 then i := Pos(#10'http://',Result) + 1;
    j := 0;
    while ((i+j) <= Length(Result)) and (Result[i+j] <> #32) do Inc(j);
    Insert('</a>',Result,i+j);
    Insert('<a href="' + Copy(Result,i,j) + '"target=_blank>',Result,i);
  end;
  while Pos(#13#10,Result) > 0 do
  begin
    i := Pos(#13#10,Result);
    Delete(Result,i,2);
    Insert('<br>',Result,i);
  end;
  while Pos('  ',Result) > 0 do
  begin
    i := Pos('  ',Result);
    Delete(Result,i,2);
    Insert('&nbsp; &nbsp;',Result,i);
  end;
  while Pos('{',Result) > 0 do Result[Pos('{',Result)] := '<';
  while Pos('}',Result) > 0 do Result[Pos('}',Result)] := '>';
  while Pos('<$APPTYPE CONSOLE>',Result) > 0 do
  begin
    i := Pos('<$APPTYPE CONSOLE>',Result);
    Result[i] := '{';
    Result[i+17] := '}';
  end;
  while Pos('< Private declarations >',Result) > 0 do
  begin
    i := Pos('< Private declarations >',Result);
    Result[i] := '{';
    Result[i+23] := '}';
  end;
  while Pos('< Public declarations >',Result) > 0 do
  begin
    i := Pos('< Public declarations >',Result);
    Result[i] := '{';
    Result[i+22] := '}';
  end;
end;


procedure TIWForm1.IWAppFormCreate(Sender: TObject);
var
  i: Integer;
begin
  CategoryID := 0;
//ADOConnection1.ConnectionString := 'Provider=SQLOLEDB.1;Password=ds9sisko;Persist Security Info=True;User ID=sa;Initial Catalog=weblog;Data Source=UNIMATRIX\SQLEXPRESS';
  for i:=0 to High(Board) do Board[i] := 0;

  TIWIPhoneStyle1.IconImage := '/Files/eBob42.png';
  TIWIPhoneStyle1.StartupImage := '/Files/Splash.png';

  Query.Active := False;
  Query.SQL.Clear;
  Query.SQL.Text := 'SELECT COUNT(Title) AS Total FROM Entry WHERE BOLD_TYPE = 0';
  Query.Active := True;

//  TIWIPhoneMenu1.Items.Clear;
//  for i:=0 to 3-1 do TIWIPhoneMenu1.Items.Add;
  TIWIPhoneMenu1.Items[0].Caption := 'Posts';
  TIWIPhoneMenu1.Items[0].Image := '/files/star.png';
  TIWIPhoneMenu1.Items[0].SelectedImage := '/files/star_s.png';
  TIWIPhoneMenu1.Items[0].IndicatorVisible := True;
  TIWIPhoneMenu1.Items[0].IndicatorCaption := Query.FieldByName('Total').AsString;

  Query.Active := False;
  Query.SQL.Clear;
  Query.SQL.Text := 'SELECT COUNT(Category.Name) AS Total FROM Category';
  Query.Active := True;

  TIWIPhoneMenu1.Items[1].Caption := 'Categories';
  TIWIPhoneMenu1.Items[1].Image := '/files/graph.png';
  TIWIPhoneMenu1.Items[1].SelectedImage := '/files/graph_s.png';
  TIWIPhoneMenu1.Items[1].IndicatorVisible := True;
  TIWIPhoneMenu1.Items[1].IndicatorCaption := Query.FieldByName('Total').AsString;

  TIWIPhoneMenu1.Items[2].Caption := 'TicTacToe';
  TIWIPhoneMenu1.Items[2].Image := '/files/preferences.png';
  TIWIPhoneMenu1.Items[2].SelectedImage := '/files/preferences_s.png';

  TIWIPhoneMenu1.SelectedIndex := 0;

  Query.Active := False;
  Query.SQL.Clear;
  Query.SQL.Text := 'SELECT Entry.BOLD_ID, Entry.Title, Entry.Posted, Entry.Author, Post.Contents FROM Entry, Post ' +
    ' WHERE (Post.BOLD_ID = Entry.BOLD_ID) ' +
    ' ORDER BY Entry.Posted DESC';
  Query.Active := True;

  Query.First;
  TIWIPhoneList1.Items.Clear;
  i := 0;
  while not Query.Eof do
  begin
    Inc(i);
    with TIWIPhoneList1.Items.Add() do
    begin
      Detail := true;
//    if (DataSource1.DataSet.FieldByName('Image').AsString <> '') then
//      Image := '/files/' + DataSource1.DataSet.FieldByName('Image').AsString;
      Caption := Query.FieldByName('Title').AsString;
      Value := ''; // 'Bob'; // DataSource1.DataSet.FieldByName('Author').AsString;
      Notes := Query.FieldByName('Posted').AsString;
      Tag := Query.FieldByName('BOLD_ID').AsInteger;
      Data.Add(ProcessContents(Query.FieldByName('Contents').AsString));
//    if not VarIsNull(DataSource1.DataSet.FieldByName('Comment').AsString) then
//      Data.Add(DataSource1.DataSet.FieldByName('Comment').AsString)
//    else Data.Add('');
    end;
    Query.Next;
  end;
  TIWIPhoneMenu1.Items[0].IndicatorCaption := IntToStr(i);
  TIWIPhoneList1.ItemAppearance.Height := 59;
  TIWIPhoneList1.ItemAppearance.DetailMargins.Top := 0;
  TIWIPhoneList1.ItemAppearance.DetailMargins.Left := 2;
end;

procedure TIWForm1.TIWIPhoneHeader1LeftButtonClick(Sender: TObject);
begin
  Release; // not Async
end;

procedure TIWForm1.TIWIPhoneHeaderRightButtonClick(Sender: TObject);
begin
  WebApplication.ShowMessage('iBlog (c) 2011 by eBob42');
end;

procedure TIWForm1.TIWIPhoneHeader2AsyncLeftButtonClick(Sender: TObject;
  EventParams: TStringList);
begin
  TIWIPhonePageFlip1.SlideToFront
end;

procedure TIWForm1.TIWIPhoneHeader3LeftButtonClick(Sender: TObject);
var
  i: Integer;
begin
  Query.Active := False;
  Query.SQL.Clear;
  Query.SQL.Text := 'SELECT Entry.BOLD_ID, Entry.Title, Entry.Posted, Entry.Author, Category.Name, Post.Contents FROM Entry, Post, Category, Categorization ' +
   ' WHERE (Category.BOLD_ID = Categorization.Categories) ' +
   '   AND (Categorization.Posts = Post.BOLD_ID) ' +
   '   AND (Post.BOLD_ID = Entry.BOLD_ID) ' +
   '   AND Category.BOLD_ID =  ' + IntToStr(CategoryID) +
   ' ORDER BY Entry.Posted';
  Query.Active := True;

  Query.First;
  TIWIPhoneList1.Items.Clear;
  i := 0;
  while not Query.Eof do
  begin
    Inc(i);
    with TIWIPhoneList1.Items.Add() do
    begin
      Detail := true;
//    if (DataSource1.DataSet.FieldByName('Image').AsString <> '') then
//      Image := '/files/' + DataSource1.DataSet.FieldByName('Image').AsString;
      Caption := Query.FieldByName('Title').AsString;
      Value := ''; // 'Bob'; // DataSource1.DataSet.FieldByName('Author').AsString;
      Notes := Query.FieldByName('Posted').AsString;
      Tag := Query.FieldByName('BOLD_ID').AsInteger;
      Data.Add(ProcessContents(Query.FieldByName('Contents').AsString));
//    if not VarIsNull(DataSource1.DataSet.FieldByName('Comment').AsString) then
//      Data.Add(DataSource1.DataSet.FieldByName('Comment').AsString)
//    else Data.Add('');
    end;
    Query.Next;
  end;
  TIWIPhoneMenu1.Items[0].IndicatorCaption := IntToStr(i);

  TIWIPhonePageFlip1.Visible := True;
  if not TIWIPhoneRegion1.Visible then TIWIPhoneRegion1.Visible := True;
  if not TIWIPhoneRegion2.Visible then TIWIPhoneRegion2.Visible := True;
  if TIWIPhoneRegion3.Visible then TIWIPhoneRegion3.Visible := False;
  if TIWIPhoneRegion4.Visible then TIWiPhoneRegion4.Visible := False;
end;

procedure TIWForm1.TIWIPhoneList1AsyncItemClick(Sender: TObject;
  EventParams: TStringList; ItemIndex: Integer);
begin
  IWLabel1.Text := TIWIPhoneList1.Items[ItemIndex].Caption;
  IWLabel2.Text := TIWIPhoneList1.Items[ItemIndex].Notes;
  TIWIPhoneScrollRegion1.Height := 1000;
  IWText1.Text := TIWIPhoneList1.Items[ItemIndex].Data.Strings[0];
  IWText1.Height := 1000;
  TIWIPhonePageFlip1.SlideToBack;
end;

procedure TIWForm1.TIWIPhoneList2AsyncItemClick(Sender: TObject;
  EventParams: TStringList; ItemIndex: Integer);
begin
  CategoryID := TIWiPhoneList2.Items[ItemIndex].Tag
end;

procedure TIWForm1.TIWIPhoneMenu1ItemClick(Sender: TComponent;
  ItemIndex: Integer);
begin
  if (ItemIndex = 0) then // Home
  begin
    TIWIPhonePageFlip1.Visible := True;
    if not TIWIPhoneRegion1.Visible then TIWIPhoneRegion1.Visible := True;
    if not TIWIPhoneRegion2.Visible then TIWIPhoneRegion2.Visible := True;
    if TIWIPhoneRegion3.Visible then TIWIPhoneRegion3.Visible := False;
    if TIWIPhoneRegion4.Visible then TIWiPhoneRegion4.Visible := False;
  end
  else if (ItemIndex = 1) then // Category
  begin
    TIWIPhoneList2.Items.Clear;
    TIWIPhoneList2.ListType := ltSettings;

    with TIWIPhoneList2.Items.Add do
    begin
      Section := True;
      Caption := 'Filter on Category';
    end;

    Query.Active := False;
    Query.SQL.Clear;
    Query.SQL.Text := 'SELECT COUNT(Title) As Total FROM Entry WHERE BOLD_TYPE = 0';
    Query.Active := True;

    with TIWIPhoneList2.Items.Add do
    begin
      Caption := 'All';
      Value := Query.FieldByName('Total').AsString;
      Tag := -1 // SQLQuery1.FieldByName('BOLD_ID').AsString;
    end;

    Query.Active := False;
    Query.SQL.Clear;
    Query.SQL.Text := 'SELECT Category.BOLD_ID, Category.Name, COUNT(Categorization.Posts) AS Total FROM Category, Categorization ' +
       ' WHERE Category.BOLD_ID = Categorization.Categories ' +
       ' GROUP BY Category.BOLD_ID, Category.Name ' +
       ' ORDER BY Category.Name';
    Query.Active := True;

    Query.First;
    while not Query.Eof do
    begin
      with TIWIPhoneList2.Items.Add do
      begin
        Caption := Query.FieldByName('Name').AsString;
        Value := Query.FieldByName('Total').AsString;
        Tag := Query.FieldByName('BOLD_ID').AsInteger;
//      Image := '/Files/' + DataSource1.DataSet.FieldByName('Country').AsString + '.png';
      end;
      Query.Next;
    end;
    if TIWIPhonePageFlip1.Visible then TIWIPhonePageFlip1.Visible := False;
    if TIWIPhoneRegion1.Visible then TIWIPhoneRegion1.Visible := False;
    if TIWIPhoneRegion2.Visible then TIWIPhoneRegion2.Visible := False;
    if not TIWIPhoneRegion3.Visible then TIWIPhoneRegion3.Visible := True;
    if TIWIPhoneRegion4.Visible then TIWiPhoneRegion4.Visible := False;
  end
  else if (ItemIndex = 2) then
  begin
    if TIWIPhonePageFlip1.Visible then TIWIPhonePageFlip1.Visible := False;
    if TIWIPhoneRegion1.Visible then TIWIPhoneRegion1.Visible := False;
    if TIWIPhoneRegion2.Visible then TIWIPhoneRegion2.Visible := False;
    if TIWIPhoneRegion3.Visible then TIWIPhoneRegion3.Visible := False;
    if not TIWIPhoneRegion4.Visible then TIWiPhoneRegion4.Visible := True;
  end;
end;

// Tic Tac Toe

  function TIWForm1.WinMove(ID: TPlayer): TPlace;
  { WinMove is in fact only a no-loose move using the magic square
    algorithm:
                8  3  4
                1  5  9
                6  7  2

    If any three (different) moves of the same player result in a
    sum of 15, then this player has won. The same MS-algorithm is
    used to find the next move to win, or prevent the opponent to
    win.
  }
  var
    tmp,i,j: Integer;
  begin
    tmp := 0;
    i := 0;
    repeat
      Inc(i);
      if Board[i] = ID then
      begin
        j := i;
        if j < LastPlace then
        repeat
          Inc(j);
          if Board[j] = ID then
          begin
            tmp := 15 - i - j;
            if (tmp < 1) or (tmp > LastPlace) or
               (Board[tmp] <> NoneID) then tmp := 0
          end
        until (j >= LastPlace) or (tmp <> 0)
      end
    until (i >= LastPlace) or (tmp <> 0);
    WinMove := tmp
  end {WinMove};

  procedure TIWForm1.MakeMove(ID: TPlayer; Place: TPlace); export;
  { Insert the move Place from handle Game, played by player ID.
  }
  begin
    Board[Place] := ID
  end {MakeMove};

  function TIWForm1.NextMove(ID: TPlayer): TPlace; export;
  { Determine next move, using internal routine WinMove if needed.
    Only use the 'magic square' algorithm  if more than two moves
    have beem made, otherwise use 'common sense'.
  }
  var
    place,last,moves: Integer;
  begin
    moves := 0;
    last := 0;
    for place := LastPlace downto 1 do
    begin
      if Board[place] <> NoneID then
      begin
        if Board[place] <> ID then last := place;
        Inc(moves)
      end
    end;

    case moves of
      0: place := 5;
      1: if Board[5] = NoneID then place := 5
                              else place := 2;
      2: if not odd(last) then place := 10 - last
         else
           if last < 5 then place := 8 { 1,3 }
                       else place := 2 { 7,9 };
{!!.2}3: begin
           place := WinMove(PlusID-ID);
           if place = 0 then
           begin
             place := LastPlace -1;
             while (place > 0) and
                   (Board[place] <> NoneID) do Dec(place,2);
             {
             last := 0;
             place :=  LastPlace;
             while place > 0 do
             begin
               if GameBoard[Game].Board[place] = PlusID-ID then
                 Inc(last,place);
               Dec(place,2)
             end;
             if (last > 0) and not odd(last) then
               place := (20 - last) SHR 1
             else place := 0;
             if place = 0 then place := WinMove(Game,PlusID-ID);
             if place = 0 then
             begin
               place := LastPlace;
               while GameBoard[Game].Board[place] <> NoneID do Dec(place)
             end
             }
           end
{!!.2}   end
      else
      begin
        place := WinMove(ID);
        if place = 0 then place := WinMove(PlusID-ID);
        if place = 0 then
        begin
          place := LastPlace;
          while Board[place] <> NoneID do Dec(place)
        end
      end
    end;
    NextMove := place
  end {NextMove};

  function TIWForm1.IsWinner: TPlayer; export;
  { If any three (different) moves of the same player result in a
    sum of 15, then this player has won. The same MS-algorithm is
    used to find the next move to win, or prevent the opponent to
    win.
  }
  var
    ID,tmp,i,j: Integer;
    Win: Boolean;
  begin
    ID := PlusID;
    Win := False;
    repeat
      Dec(ID);
      i := 0;
      repeat
        Inc(i);
        if Board[i] = ID then
        begin
          j := i;
          if j < LastPlace then
          repeat
            Inc(j);
            if Board[j] = ID then
            begin
              tmp := 15 - i - j;
              Win := (tmp > j) and (tmp <= LastPlace) and
                     (Board[tmp] = ID)
            end
          until (j >= LastPlace) or Win
        end
      until (i >= lastPlace) or Win
    until (ID = NoneID) or Win;
    IsWinner := ID mod PlusID
  end {IsWinner};

  function TIWForm1.GetValue(Place: TPlace): TPlayer; export;
  begin
    GetValue := Board[Place];
  end {GetValue};


procedure TIWForm1.AsyncButtonClick(Sender: TObject;
  EventParams: TStringList);
var
  Next: Integer;
begin
  (Sender as TIWButton).Enabled := False;
  (Sender as TIWButton).Caption := '0';
  MakeMove(UserID, (Sender as TIWButton).Tag);
  if IsWinner = UserID then WebApplication.ShowMessage('You have won!');
  Next := NextMove(CompID);
  MakeMove(CompID, Next);
  case Next of
    1: begin btn1.Caption := 'X'; btn1.Enabled := False end;
    2: begin btn2.Caption := 'X'; btn2.Enabled := False end;
    3: begin btn3.Caption := 'X'; btn3.Enabled := False end;
    4: begin btn4.Caption := 'X'; btn4.Enabled := False end;
    5: begin btn5.Caption := 'X'; btn5.Enabled := False end;
    6: begin btn6.Caption := 'X'; btn6.Enabled := False end;
    7: begin btn7.Caption := 'X'; btn7.Enabled := False end;
    8: begin btn8.Caption := 'X'; btn8.Enabled := False end;
    9: begin btn9.Caption := 'X'; btn9.Enabled := False end;
  end;
  if IsWinner = CompID then WebApplication.ShowMessage('I have won!!');
end;

procedure TIWForm1.TIWIPhoneButton10AsyncButtonClick(Sender: TObject;
  EventParams: TStringList);
begin
  FillChar(Board,SizeOf(Board),0);
  btn1.Caption := ' '; btn1.Enabled := True;
  btn2.Caption := ' '; btn2.Enabled := True;
  btn3.Caption := ' '; btn3.Enabled := True;
  btn4.Caption := ' '; btn4.Enabled := True;
  btn5.Caption := ' '; btn5.Enabled := True;
  btn6.Caption := ' '; btn6.Enabled := True;
  btn7.Caption := ' '; btn7.Enabled := True;
  btn8.Caption := ' '; btn8.Enabled := True;
  btn9.Caption := ' '; btn9.Enabled := True;
end;


initialization
  TIWForm1.SetAsMainForm;
end.



SELECT COUNT(Title) FROM Entry WHERE BOLD_TYPE = 0
GO
--SELECT SUM(X.COUNTER) FROM (
  SELECT Category.BOLD_ID, Category.Name, COUNT(Categorization.Posts) AS COUNTER FROM Category, Categorization
   WHERE Category.BOLD_ID = Categorization.Categories
GROUP BY Category.BOLD_ID, Category.Name
ORDER BY Category.Name
--) X
GO
  SELECT Entry.BOLD_ID, Entry.Title, Entry.Posted, Entry.Author, Category.Name, Post.Contents FROM Entry, Post, Category, Categorization
   WHERE (Category.BOLD_ID = Categorization.Categories)
     AND (Categorization.Posts = Post.BOLD_ID)
     AND (Post.BOLD_ID = Entry.BOLD_ID)
     AND Category.BOLD_ID = 4
ORDER BY Entry.Posted
GO
SELECT COUNT(Category.Name) FROM Category


Post.BOLD_ID
Post.Contents

Entry.BOLD_ID
Entry.Title
Entry.Posted.Author

Comment.BOLD_ID
Comment.Comments
Comment.Post

Categorization.Post
Categorization.Categories

Category.BOLD_ID
Category.Name

