Skip to content
Shiva Wu edited this page Jan 5, 2014 · 11 revisions

In Greed, Templates are used to generating code to test your program against the example test cases. Many other plugins, like FileEdit, supports templates, too. But in Greed, templates are much more powerful and completely flexible. You can involve in almost every step of the code generation and take full control of the generating process.

Examples

There are too many details for me to describe when writing a template. The best way to learn this is through examples. Here're some default templates in which you can work based on. If you have finished reading other pages, you must've understand what these templates are.

C++ File Test Template

Problem statement template

Java source code template

I'll cover some basic knowledge of the template engine in the following section.

Template Engine

To fully enable the power of template, we use a lightweight template engine jmte. It's efficient, simple, and enough powerful (maybe not :3).

If you're interested in this engine, read its documentation.

But as in Configuration, I'll briefly describe the template language, although the documentation of jmte has done such a thing. I've made several changes to the template itself, so we have to describe these things.

Template language

Template keys are surrounded by ${ and }. Anything else will be directly copied to the rendering result.

Templates are translated based on a model. The model is a String->Object mapping, in which Object can be anything.

Meta keys

jmte provided built-in functional templates like ${if}, ${foreach}, described below:

  • ${if X}...${else}...${end} - if key X is found in the model, the ... is inserted, the ${else} is optional.
  • ${foreach values v , }...${end} - values is a iterable object, and the loop will bind v to every value in values, v will be put in the model while in the scope in the .... A , is inserted after every ... block, except the last one.

Recall the ${Contest.Name} in pathPattern? If you wanna, you can write ${Contest.Name}${if Contest.Div}/DIV ${Contest.Div}${end}. It'll produce folder path like SRM 257/DIV 2 if SRM 257 contest has a division, or just SRM 257 if not.

How the template engine resolves the key

When rendering a data like ${a.xyz.uvw}, the template engine usually do the following:

  1. Find a key in the map called a, if not present, returns "".
  2. If present, check its value
    • If it's an object o, try the following until found one available: o.getXyz(), o.isXyz(), o.xyz (public field)
    • If it's another map, goto 1
    • Otherwise, returns ""

When it hits the final key in the path, uvw in this case, and now the value is o, the result is

  • If o is of a primitive type, returns its string representation
  • If o is an raw object, first find a typed renderer based on its class
  • If not found, call its toString

Like in the following table, Contest is an object of type greed.model.Contest, hence ${Contest.Name} represents the full contest name.

Better formatting with <

This part is not available in the official version of jmte.

One of the limitation of the template mechanism above, is that the template cannot do anything about the plain text outside the template. So if I write,

${foreach ...}
${end}

See? There're two blank lines after each tag, and will be inserted into the result. That's not good practice for a programming code. So what I did, is that, you can change the above to:

${<foreach ...}
${<end}

The < is like an option to the tag token. It will remove the directly following newline. It will work on any tag.

In this way, we can get a better formatted code.

Difference between config and template

Although the config library and the template engine uses the same syntax for resolving data, ${key}, they're of different implementations and have different semantics. In the config file, ${a.b.c} means the value of a.b.c following the path from the root of the config file. However, in the template file, ${a.b.c} simply binds to the value inside a map m, which is m.get("a").get("b").get("c"). This is the core difference.

Sometimes (often) Greed needs to specify some data in the config file, like ${Problem.Name}, for example, to specify the output file name. And we must prevent the config library to resolve this reference in its way. We achieve this by putting the value in quotation, that's why you'll see a lot of "" in the default.conf.

Named Renderers

It's also possible to have named renderers in the template engine, in this format ${data;name_of_renderer(param)}. These renderers define custom functions to render the data, according to its param.

Available named renderers in Greed:

  • format, accepts a string as input and a format string as params. It calls String.format in Java directly and returns the result.
  • zeroval, no params, whose data must be a type (greed.model.Type), and it returns a string representing its zero value in the current language.
  • string is a generic string transformation renderer, the data is a String, and its params is also a string which is a list of actions to perform on the input, and they are concatenated with commas. The actions are applied one by one, in sequential order. The available actions are:
    • lower - to lower case
    • upcasefirst - uppercase the first letter and lowercase the rest
    • unquote - remove the surrounding " in the string, if any
    • abbr - abbreviate the input, by transforming all its all-uppercase tokens to its first letter and then joining them together
  • category: A special renderer for objects of type greed.model.Contest intended to help organize code folders:
    • If the given string contains Topcoder open or TCO , the returned result is TCO.
    • If the given string contains TCHS , the returned result is TCHS.
    • If the given string name contains TCCC, the returned result is TCCC
    • If the given string name contains Single Round Match XXX or SRM XXX where XXX is a number, then it returns SRM. This behavior can be modified by using the srm=X parameter, where X is a interval length. For example: `Contest;category(srm=25) will do the following:
      • SRM 597, Single Round Match 575 and Single Round Match 599 become SRM 575-599.
      • SRM 525.5, SRM 530 and SRM 536 become SRM 525-549.
    • If the string doesn't match any of the mentioned patterns, the renderer returns Other.
  • parser is only available for java and python language, whose data is of type greed.model.Type, and its param is a string. It returns a parsing expression in that language, which parses the param to its input type. Like in Java, ${type;parser(numBeans)} transforms to Integer.parseInt(numBeans) if type is of integer.
  • html is intended to help in problem statement templates. If the input is of type String (specially String values in example test cases), it will escape any HTML entities (e.g: Turns " into &quot;). Most importantly, if the input is a greed.model.ParamValue or a greed.model.Type, it will format it for it to be displayed in HTML:
  • paramval;html : Renders Param Value parameters - will always render String[] parameters in a single line.
  • paramval;html("grid") : Will render some String[] parameters as if they were 2D grids. Using multiple lines. If all elements in the String[] have the same length, it will assume it is a grid.
  • type;html(lang) : Renders the type name in language lang. lang can be: cpp, java, python, csharp.

You can use these renderers to write your template and also in the configuration file. The string renderer is especially useful for things like changing the ContestName to lowercase, or to its abbreviation.

There're also two advanced named renderers, which is used to strengthen the power of the template engine, you will be very likely not using them.

  • seq(params), is a named renderer inside template engine. It takes anything as input, and takes a sequence of expressions as params. It transform the input via a series of renderers, giving the engine the ability of sequential and nested operations. It does two things.
    • Resolve all the variables in the params expressions, starting with $ and ending with one of the symbols in (),. Resolve means rendering using the engine.
    • Iterate the input with each expression, by first binding it to some random key K, then
      • If the exp is #, meaning no named renderer, just render ${K}
      • Otherwise it's a named renderer, render ${K;exp}.
  • reify, takes a string input and render it using the engine. It's just rendering the input as a key, enabling the ability for some renderer to output a key, then reifying it to a value.

List of key-values

Here's a table for all the keys and their values with their available scopes.

Key Name Value Scope Class/Type
Contest The contest object config + template greed.model.Contest
Problem The current problem object config + template greed.model.Problem
ClassName The class name for the current problem config + template String
Method The method name config + template String
Examples The list of samples given template greed.model.Testcase
NumOfExamples The number of samples template String
ReturnsArray Whether the method returns an array template Boolean
HasArray Whether the method returns an array or one of the parameter is an array template Boolean
ReturnsString Whether the method returns a string template Boolean
HasString Similar to HasArray template Boolean
CreateTime A time tag when the code is created, to calc the score template Long
CutBegin The begin-cut mark for the current language template String
CutEnd The end-cut mark template String
GeneratedFileName The generated file name afterFileGen String
GeneratedFilePath The generated file path afterFileGen String

Examples of Predefined variables

Here's a list of examples which you can use in your template. They're all available in the previous table, but more specific and with concrete values. We use C++ as the current language.

Value Name Example Comment
Contest.Name SRM 257 Contest name
Contest.Div 1 Contest division number
Problem.Name RabbitWorking Problem name
Problem.Score 1000 Problem score, in integer
Problem.MemoryLimitMB 256 The problem's memory limit in MB. Old TC problems have a 64 MB limit. Most but not all of recent problems will have 256.
Problem.TimeLimitMillis 2000 The problem's time limit in milliseconds. Most but not all problems have a time limit of 2000 milliseconds.
Problem.TimeLimitSeconds 2.0 A floating point variable equivalent to Problem.TimeLimitMillis / 1000.0.
ClassName StangeDictionary2 Class name
Method.Name getProbabilities Method name
Method.Params vector<string> words Method parameter list, splitted by ,
Method.ReturnType vector<int> Method return type, will be bound to type identifier according to current language
Method.ReturnType;zeroval vector<int>() A special renderer for a default return value.
TestCode Too long to show... This is the default key where the template filetest and test bound to, and will be put in the source template

A table of value names related to test samples.

Value Name Comment
Examples Example object list, each of which is of type Testcase. Iterate over it using ${foreach Examples e}.
e.Num the example number of e(a Testcase object above)
e.Input A list of ParamValue represents the input, each for one parameter
e.Output The output value of this example, let it be parVal below
parVal.Param This is a Param object let it be p below
p.Name The name of a parameter
p.Index The index of a parameter (0-indexed)
p.Type The type of a parameter, it is a type object(we call it t)
t.Primitive the primitive type of t, like String, int
t.Array Set to true if t represents an array
t.RealNumer Set to true if the primitive type in t is double
t.String Set to true if the primitive type in t is String
t.LongInteger Set to true if the primitive type in t is long
parVal.Value the given value of this param
parVal.ValueList The value list, if it's an array, can be iterated on via ${foreach}
NumOfExamples Number of example test cases. A workaround for the not-working ${Examples.length}

And a table of values related to problem statement.

Value Name Comment
Problem.Description Returns a ProblemDescription object for the problem. In the following rows we will refer to it as desc
desc.Intro The problem introduction HTML
desc.HasNotes True if the problem statement has a Notes section
desc.Notes Returns a list of problem notes. Each note is a HTML string
desc.Constraints Returns a list of constraints.
e.Annotation If example e has an annotation contains HTML of the annotation. Else it is null
desc.Modulo Greed tries to parse the statement, if it finds the pattern "Modulo NUMBER", it will store the NUMBER in the desc.Modulo value. Use ${if Problem.Description.Modulo} to find if this value exists