(*
    Checker for NEERC'2007 Problem F: Fund Management
    (C) Roman Elizarov
*)

{$O+,Q+,R+}
{$APPTYPE CONSOLE}

program Check;

uses
  TestLib, SysUtils, Math;

const
  BASE = 1000;
  BDIG = 3;
  PREC = 2; // assert PREC = BGIG - 1 (used in ToString)
  POW : array[0..BDIG-1] of Integer = (1, 10, 100);

type
  TMoney = class 
    v : array of Integer;

    constructor Parse(var ins: InStream);
    function ToString: String;
    function Compare(o: TMoney): Integer;
    procedure Add(o: TMoney);
    procedure Sub(o: TMoney);
    procedure AddInt(x: Integer);
    procedure MulInt(k: Integer);
  end;

constructor TMoney.Parse(var ins: InStream);
var
  s: String;
  i, z: Integer;
  d: Boolean;
begin
  s := ins.ReadWord(NumberBefore, NumberAfter);
  if Length(s) > 100 then
    ins.Quit(_PE, Format('The number is too long "%s"', [s]));
  z := 0;
  d := false;
  for i := 1 to Length(s) do begin
    if (s[i] >= '0') and (s[i] <= '9') then begin
      if d then begin
        Inc(z);
        if z > PREC then 
          ins.Quit(_PE, Format('Too many digits after decimal point in "%s"', [s]));
      end;
      MulInt(10);
      AddInt(Ord(s[i]) - Ord('0'));
    end else if (s[i] = '.') and not d then begin
      d := true;
    end else
      ins.Quit(_PE, Format('Invalid number "%s"', [s]));
  end;
  while z < PREC do begin
    Inc(z);
    MulInt(10);
  end;
end;

function TMoney.ToString: String;
var
  i, j, x: Integer;
  f: Boolean;
begin
  f := false;
  Result := '';
  for i := Length(v) - 1 downto 0 do begin
    for j := BDIG - 1 downto 0 do begin
      x := (v[i] div POW[j]) mod 10;
      if f or (x <> 0) or (i = 0) then begin
        Result := Result + Chr(x + Ord('0'));
        f := true;
      end;
    end;
  end;
  Result := Copy(Result, 1, Length(Result) - 2) + '.' + Copy(Result, Length(Result) - 1, 2);
end;

function TMoney.Compare(o: TMoney): Integer;
var 
  i, a, b: Integer;
begin
  for i := Max(Length(v), Length(o.v)) - 1 downto 0 do begin
    if i < Length(v) then a := v[i] else a := 0;
    if i < Length(o.v) then b := o.v[i] else b := 0;
    if a < b then begin
      Result := -1;
      Exit;
    end;
    if a > b then begin
      Result := 1;
      Exit;
    end;
  end;
  Result := 0;
end;

procedure TMoney.Add(o: TMoney);
var
  i, x, a, b: Integer;
begin
  x := 0;
  for i := 0 to Max(Length(v), Length(o.v)) - 1 do begin
    if i < Length(v) then a := v[i] else a := 0;
    if i < Length(o.v) then b := o.v[i] else b := 0;
    Inc(x, a + b);
    if i >= Length(v) then
      SetLength(v, i + 1);
    v[i] := x mod BASE;
    x := x div BASE;
  end;
  while x > 0 do begin
    SetLength(v, Length(v) + 1);
    v[Length(v) - 1] := x mod BASE;
    x := x div BASE;
  end;
end;

procedure TMoney.Sub(o: TMoney);
var
  i, x, y, a, b: Integer;
begin
  x := 0;
  for i := 0 to Max(Length(v), Length(o.v)) - 1 do begin
    if i < Length(v) then a := v[i] else a := 0;
    if i < Length(o.v) then b := o.v[i] else b := 0;
    Inc(x, a - b);
    if i >= Length(v) then
      SetLength(v, i + 1);
    y := 0;
    while x < 0 do begin
      Inc(x, BASE);
      Dec(y, 1);
    end;
    v[i] := x;
    x := y;
  end;
  if x < 0 then
    Quit(_FAIL, 'Wrong call to sub -- negative result');
end;

procedure TMoney.AddInt(x: Integer);
var
  i: Integer;
begin
  for i := 0 to Length(v) - 1 do begin
    Inc(v[i], x);
    x := v[i] div BASE;
    v[i] := v[i] mod BASE;
    if x = 0 then
      Exit;
  end;
  SetLength(v, Length(v) + 1);
  v[Length(v) - 1] := x;
end;

procedure TMoney.MulInt(k: Integer);
var
  i, x: Integer;
begin
  x := 0;
  for i := 0 to Length(v) - 1 do begin
    v[i] := v[i] * k + x;
    x := v[i] div BASE;
    v[i] := v[i] mod BASE;
  end;
  while x > 0 do begin
    SetLength(v, Length(v) + 1);
    v[Length(v) - 1] := x mod BASE;
    x := x div BASE;
  end;
end;

var
  c: TMoney;
  m, n, k: Integer;
  name: array of String;
  si, ki, w: array of Integer;
  p: array of array of TMoney;
  i, j, t: Integer;
  ja, pa: TMoney;
  op: String;

function FindStock(s: String): Integer;
begin
  for Result := 0 to Length(name) - 1 do 
    if s = name[Result] then
      Exit;
  Result := -1; // just to avoid warning message
  Quit(_WA, Format('Stock name is not found "%s"', [s]));
end;

begin
  c := TMoney.Parse(inf);
  m := inf.ReadInteger();
  n := inf.ReadInteger();
  k := inf.ReadInteger();
  SetLength(name, n);
  SetLength(si, n);
  SetLength(ki, n);
  SetLength(w, n);
  SetLength(p, n);
  for i := 0 to n - 1 do begin
    name[i] := inf.ReadWord(NumberBefore, NumberAfter);
    si[i] := inf.ReadInteger();
    ki[i] := inf.ReadInteger();
    w[i] := 0;
    SetLength(p[i], m);
    for j := 0 to m - 1 do begin
      p[i][j] := TMoney.Parse(inf);
      p[i][j].MulInt(si[i]);
    end;
  end;

  pa := TMoney.Parse(ouf);
  if not ouf.SeekEoln then
    Quit(_PE, 'Extra data on first line');
  ouf.NextLine();
  t := 0;
  for j := 0 to m - 1 do begin
    op := ouf.ReadString();
    if op = 'HOLD' then
      continue;
    if Copy(op, 1, 4) = 'BUY ' then begin
      i := FindStock(Copy(op, 5, Length(op) - 4));
      Inc(w[i]);
      if w[i] > ki[i] then
        Quit(_WA, Format('Bought too much of %s', [name[i]]));
      Inc(t);
      if t > k then 
        Quit(_WA, 'Bought too much lots');
      if c.Compare(p[i][j]) < 0 then
        Quit(_WA, Format('Not enough money to buy %s, remaining %s, required %s', [name[i], c.ToString, p[i][j].ToString]));
      c.Sub(p[i][j]);
      continue;
    end;
    if Copy(op, 1, 5) = 'SELL ' then begin
      i := FindStock(Copy(op, 6, Length(op) - 5));
      if w[i] <= 0 then
        Quit(_WA, Format('Does not have %s to sell', [name[i]]));
      Dec(w[i]);
      Dec(t);
      c.Add(p[i][j]);
      continue;
    end;
    Quit(_PE, Format('Wrong operation "%s"', [op]));
  end;
  if not ouf.SeekEof then
    Quit(_PE, 'Extra lines in output');

  if c.Compare(pa) <> 0 then
    Quit(_WA, Format('Plan does not match answer amount %s <> %s', [pa.ToString, c.ToString]));


  ja := TMoney.Parse(ans);
  if ja.Compare(pa) < 0 then
    Quit(_FAIL, Format('Answer is better %s > %s', [pa.ToString, ja.ToString]));
  if ja.Compare(pa) <> 0 then
    Quit(_WA, Format('Wrong answer %s <> %s', [pa.ToString, ja.ToString]));

  Quit(_OK, Format('%s in %d days', [c.ToString, m]));
end.
