import java.io.BufferedWriter;

import java.util.Enumeration;
import java.util.Hashtable;
import java.util.LinkedList;

import java.io.*;
import java.util.StringTokenizer;
import java.util.NoSuchElementException;

/** Class ContestInput reads in and parses lines of stdin.
	After creation ContestInput reads in one line of input and defines a
	StringTokenizer for that line via method readline( ). While this
	Tokenizer object still holds input the line can be consumed by
	highlevel converting methods nextInt, nextDouble, nextBoolean etc.
	There is no Tokenizer for Character, so if the inpput must consume
	single characters without blönaks in between, you must consume the
	String and read its characters in a loop yourself. Also be aware that
	Tokens are defined by white space characters (Blank, Comma, Newline, Tab, ...)
	so if you need to process those, read in the whole input line via
	static Input.readString( ).
	@author		Ulrik Schroeder
	@version 	1.0, 7-march-98
	@see java.io.BufferedReader
	@see java.io.InputStreamReader
	@see java.lang.Short
	@see java.lang.Integer
	@see java.lang.Long
	@see java.lang.Character
	@see java.lang.Boolean
 */
class ContestInput {
	//String 
//int 
	/** buffered character input stream */
    protected BufferedReader in =
    	new BufferedReader( new InputStreamReader( System.in ) );

	/** the tokenizer is instatiated for each line read by readLine( ). */
    protected StringTokenizer t;

    /** reads the next line of input and creates the associated StringTokenizer. */
    public void readLine( ) {
		try { t = new StringTokenizer( in.readLine( ) );
		} catch ( IOException e2 ) {
			System.err.println( "*** IO Exception ***" );
			System.exit( 1 );
		}
	}

	public int 		tokenCount( ) 	{ return t.countTokens( ); }
	public boolean 	hasMore( ) 		{ return t.hasMoreTokens( ); }

	///////////////////////////////////////////////   Integer types:

	/** consumes the next input token and converts into a short value
		@return		short value represented by the next token
	 */
	public short nextShort( ) {
		try { return Short.parseShort( t.nextToken( ) );
		} catch( NoSuchElementException e0 ) {
			System.err.println( "No more input available" );
		} catch( NumberFormatException e1 ) {
			System.err.println( e1.getMessage( ) );
			System.err.println( "ist keine gültige short" );
		}
		return 0;
	 } // nextShort



	/** consumes the next input token and converts into a int value
		@return		int value represented by the next token
	 */
	public int nextInt( ) {
		try { return Integer.parseInt( t.nextToken( ) );
		} catch( NoSuchElementException e0 ) {
			System.err.println( "No more input available" );
		} catch( NumberFormatException e1 ) {
			System.err.println( e1.getMessage( ) );
			System.err.println( "ist keine gültige int" );
		}
		return 0;
	 } // nextInt



	/** consumes the next input token and converts into a long value
		@return		long value represented by the next token
	 */
	public long nextLong( ) {
		try { return Long.parseLong( t.nextToken( ) );
		} catch( NoSuchElementException e0 ) {
			System.err.println( "No more input available" );
		} catch( NumberFormatException e1 ) {
			System.err.println( e1.getMessage( ) );
			System.err.println( "ist keine gültige long" );
		}
		return 0;
	 } // nextLong



	///////////////////////////////////////////////   Character:

	/** consumes the next input token and converts into a character.
		Attention: single characters must be separated by
		white space characters.
		@return		charcter represented by the next token
	 */
	public char nextChar( ) {
		return t.nextToken( ).charAt( 0 );
	 } // nextchar


	///////////////////////////////////////////////   Boolean:

	/** consumes the next input token and converts into a boolean value
		@return		boolean value represented by the next token
	 */
	public boolean nextBoolean( ) {
		return new Boolean( t.nextToken( ) ).booleanValue( );
	 } // nextBoolean



	///////////////////////////////////////////////   Float/Double:

	/** consumes the next input token and converts into a float value
		@return		float value represented by the next token
	 */
	public float nextFloat( ) {
		try { return new Float( t.nextToken( ) ).floatValue( );
		} catch( NoSuchElementException e0 ) {
			System.err.println( "No more input available" );
		} catch( NumberFormatException e1 ) {
			System.err.println( e1.getMessage( ) );
			System.err.println( "ist keine gültige float" );
		}
		return Float.NaN;
	 } // nextFloat


	/** consumes the next input token and converts into a double value
		@return		double value represented by the next token
	 */
	public double nextDouble( ) {
		try { return new Double( t.nextToken( ) ).doubleValue( );
		} catch( NoSuchElementException e0 ) {
			System.err.println( "No more input available" );
		} catch( NumberFormatException e1 ) {
			System.err.println( e1.getMessage( ) );
			System.err.println( "ist keine gültige double" );
		}
		return Double.NaN;
	 } // nextDouble


	///////////////////////////////////////////////   String:

	public String nextString( ) {
		try { return t.nextToken( );
		} catch( NoSuchElementException e0 ) {
			System.err.println( "No more input available" );
		}
		return "";
	 } // nextString

} // class ContestInput

public class cocktails
{
   static ContestInput input;
   static BufferedWriter out;
   static Hashtable recipes;
   static Hashtable ingredients;
   static Hashtable ingPrices;
   static int[] orders;
   static long[] cocktailPrices;
   static LinkedList recipeOrder;
   static String zLastOrder;

   public static void main(String[] args) throws Exception
   {
      input = new ContestInput();
      out = new BufferedWriter(new java.io.OutputStreamWriter(System.out));
      try
      {
         input.readLine();
         int nTestCaseCount = input.nextInt();
         for (int i = 1; i <= nTestCaseCount; i++)
         {
            readRecipes();
            readIngredients();
            calculatePrices();
            processOrders();
            out.write("Scenario " + i + " top cocktails:\n");
            outputResult();
         }
      }
      finally
      {
         // Force flush writer
         out.close();
      }
   }


   public static void processOrders()
   {
      input.readLine();
      int nOrderCount = input.nextInt();
      for (int i = 1; i <= nOrderCount; i++)
      {
         input.readLine();
         String zCocktailName = input.nextString();
         String zNextOrder = mixWhat(zCocktailName);
         if (zNextOrder != null)
         {
            mix(zNextOrder);
            zLastOrder = zNextOrder;
         }
      }
   }


   public static String mixWhat(String zCocktailName)
   {
      String zNextOrder = zCocktailName;
      int index = recipeOrder.indexOf(zCocktailName);
      if (index < 0) return null;

      int currentIndex = index;
      if (zCocktailName.equals(zLastOrder))
      {
         if (index == recipeOrder.size() - 1)
            currentIndex = 0;
         else
            currentIndex = index + 1;
         zNextOrder = (String)recipeOrder.get(currentIndex);
         if (zNextOrder.equals(zLastOrder))
            return null;
      }

      while ((zNextOrder.equals(zLastOrder)) || (!canBeMixed(zNextOrder)))
      {
         if (currentIndex == recipeOrder.size() - 1)
            currentIndex = 0;
         else
            currentIndex++;
         if (currentIndex == index) // nothing can be mixed
            return null;
         zNextOrder = (String)recipeOrder.get(currentIndex);
      }

      return zNextOrder;
   }


   public static boolean canBeMixed(String zCocktailName)
   {
      boolean mixable = true;
      Hashtable ingTable = (Hashtable)recipes.get(zCocktailName);
      Enumeration keyEnum = ingTable.keys();

      while (keyEnum.hasMoreElements())
      {
         String zIngName = (String)keyEnum.nextElement();
         long neededAmount = getLong(ingTable, zIngName);
         if (!isAvailable(zIngName, neededAmount))
         {
            mixable = false;
            break;
         }
      }

      return mixable;
   }


   public static void mix(String zCocktailName)
   {
      Hashtable ingTable = (Hashtable)recipes.get(zCocktailName);
      Enumeration keyEnum = ingTable.keys();

      while (keyEnum.hasMoreElements())
      {
         String zIngName = (String)keyEnum.nextElement();
         long neededAmount = getLong(ingTable, zIngName);
         long supply = getLong(ingredients, zIngName);
         putLong(ingredients, zIngName, supply - neededAmount);
      }
      orders[recipeOrder.indexOf(zCocktailName)]++;
   }


   public static void calculatePrices()
   {
      for (int i = 0; i < recipeOrder.size(); i++)
      {
         long cocktailPrice = 0;
         String zCocktailName = (String)recipeOrder.get(i);
         Hashtable ingTable = (Hashtable)recipes.get(zCocktailName);
         Enumeration keyEnum = ingTable.keys();
         while (keyEnum.hasMoreElements())
         {
            String zIngName = (String)keyEnum.nextElement();
            long ingPrice = getLong(ingPrices, zIngName);
            long amount = getLong(ingTable, zIngName);
            cocktailPrice += amount * ingPrice;
         }
         cocktailPrice *= 3;
         cocktailPrice += 10000;
         cocktailPrices[i] = cocktailPrice;
      }
   }


   public static void outputResult() throws Exception
   {
      int rank = 1;
      int outCount = 0;
      boolean[] isOut = new boolean[recipeOrder.size()];
      for (int i = 0; i < recipeOrder.size(); i++)
      {
         // no orders -> no output
         if (orders[i] == 0)
         {
            isOut[i] = true;
            outCount++;
         }
      }

      while ((rank <= 10) && (outCount < recipeOrder.size()))
      {
         int index = 0;
         int max = 0;
         for (int i = 0; i < recipeOrder.size(); i++)
         {
            if (!isOut[i])
            {
               if (orders[i] > max)
               {
                  max = orders[i];
                  index = i;
               }
            }
         }

         out.write((rank) + " " + recipeOrder.get(index) + " " + orders[index] + " " + cocktailPrices[index] + "\n");
         isOut[index] = true;
         outCount++;
         rank++;
      }
   }


   public static void readRecipes()
   {
      recipeOrder = new LinkedList();
      recipes = new Hashtable();
      input.readLine();
      int nRecipeCount = input.nextInt();
      orders = new int[nRecipeCount];
      cocktailPrices = new long[nRecipeCount];
      for (int i = 1; i <= nRecipeCount; i++)
      {
         input.readLine();
         String zName = input.nextString();
         recipeOrder.addLast(zName);
         int nIngredientsCount = input.nextInt();
         input.readLine();
         Hashtable ingTable = new Hashtable();
         for (int j = 1; j <= nIngredientsCount; j++)
         {
            String zIngredient = input.nextString();
            putLong(ingTable, zIngredient, input.nextLong());
         }
         recipes.put(zName, ingTable);
      }
   }


   public static void readIngredients()
   {
      ingredients = new Hashtable();
      ingPrices = new Hashtable();
      input.readLine();
      int nIngCount = input.nextInt();
      for (int i = 1; i <= nIngCount; i++)
      {
         input.readLine();
         String zName = input.nextString();
         putLong(ingredients, zName, input.nextLong());
         putLong(ingPrices, zName, input.nextLong());
      }
   }


   public static long getLong(Hashtable table, String zKey)
   {
      Long oLong = (Long)table.get(zKey);
      if (oLong == null)
         return 0;
      return oLong.longValue();
   }


   public static void putLong(Hashtable table, String zKey, long l)
   {
      Long oLong = new Long(l);
      table.put(zKey, oLong);
   }


   public static boolean isAvailable(String zIngName, long amount)
   {
      long supply = getLong(ingredients, zIngName);
      return (supply >= amount);
   }
}
