text:
I am in the process of creating a Rules Engine. I have architected the Rules Engine to allow the rules to be "pre-compiled" or "dynamic". The "pre-compiled" rules are simply rules that are programmed in a .Net language and invoked by the Rules Engine using reflection. The "dynamic" rules are interpreted at execution time by the Rules Engine. The "dynamic" rules offer great flexibility because they can be changed very easily.
This article is not about the Rules Engine; it is about the parser/interpreter that is built into the Rules Engine that evaluates the dynamic rules. This piece of the code that evaluates the dynamic rules is called the Evaluation Engine. Included in the download is the Evaluation Engine source code and test application. The main test application (called the Rules Calculator) allows you to enter in the rule syntax, parse the syntax, and evaluation the results.
Before going into too much detail on how the Evaluation Engine works, I thought it would be better to show you what it does. After you see what the Evaluation Engine can do, I will explain how it works. As I mentioned previously, the test application that is included is called the Rules Calculator. The Rules Calculator is simply a "wrapper" around the Evaluation Engine. The Rules Calculator allows you to type in Rules Syntax (for lack of a better name, I'll call the syntax "Rules Basic"). Next, the Rules Calculator passes the Rules Basic syntax to the Evaluation Engine for evaluation.
The job of the Evaluation Engine is to take the Rules Basic string (or .Rule file), evaluate the contents and perform the action. Most compilers and interpreters go through a process called parsing. The parsing process needs to look at the Rules Basic string and pull out the important pieces of information. The important pieces of information the parser identifies are called "tokens". Each token gets identified as a certain type of token (or classification). Each token is classified as one of the following:
An operand is a value or a variable in the Rules Basic syntax. For example, in the mathematic equation "1 + 2 = 3", the items 1, 2, and 3 are operands. Similarly, in the equation "a + -b >= c" the operands are a, b, and c. Obviously, there is a difference between the operands 1, 2, 3 and a, b, c. That is, the first set of operands are Integer values and the second set are variables. The point is that the operand tokens can be further classified by types. The Evaluation Engine classifies the Operand Tokens as one of the following:
The Rules Basic syntax allows for function on operands. This token indicates that the parser has found the start of an operand function. All operand functions in the Rules Basic syntax utilize square brackets. For example, Avg[], Year[], Join[] are 3 examples of operand functions that are available in Rules Basic. Operand functions can take operands are parameters. The Evaluation Engine does some data type checking. For example, Year[5.20.1999] operand function required an operand token of type Token_DataType_Date (notice that the date delimiter is "."). The same operand function with the wrong data type operand will throw an error, i.e., Year["Hello"] will cause an error.
The Evaluation Engine follows the mathematical order of operations. This order of operations can be changed by using parenthesis. This token indicates that the Evaluation Engine found an open parenthesis: (
The Evaluation Engine has found a close parenthesis.
The Rules Basic syntax allows for operand function. The parameters for operand functions are identified in square brackets. This token indicates that the Evaluation Engine found the end of an Operand Function.
Operand functions can take multiple parameters. The parameters in an operand functions are separated by commas. This token indicates that the Evaluation Engine has found a comma in a Operand Function
Operators are applied to operands. For example, when the "+" operator is applied to the operands 1 and 1, the result is 2. This token indicates that the Evaluation Engine has found an operator.
The Rules Basic syntax allows for assignment of variables. Variables can be assigned static values (such as "Hello") or they can be assigned Rules Basic syntax (such as "1 + 1"). The assigned variables can also participate in other Rules Basic syntax. The assignment operator is := Examples of assignments are seen in the examples below. Therefore, when the Evaluation Engine encounters a := in the Rules Basic string, a Token_Assignemt_Start gets created in the collection of tokens.
The semicolon (;) indicates the end of an assignment in Rules Basic syntax. When the Evaluation Engine detects ; a Token_Assignment_Stop token gets created.
One more important piece of information: When the Evaluation Engine parses the Rules Basic string, every token gets assigned a token type and a token data type. For example, the token "Hello" will get assigned the Token Type = Token_Operand and the Token Data Type = Token_DataType_String. If you forget to the double quotes around the string "Hello", the parser will classify Hello as a Token_Operand and data type Token_DataType_Variable. Since every token gets classified with a token type and token data type, how does the parser classify the data type of a = token, or a + token, or a ( token? The token + gets classified as token type Token_Operator and data type Token_DataType_None. I did not mention the "None" data type in the tables above because I wanted to provide this example first. Therefore, the operand tokens can be classifies as Integer, Date, Double, String, Boolean, Null, Variable or None.
Let's work through an example of parsing and tokens. We will keep the Rules Basic syntax simple: (1 + 3) * Avg[3,4,2+3] Here are the tokens that get identified in the above example:
Token Type
Token Data Type
After the Evaluation Engine identifies and classifies all the tokens in the Rules Basic syntax, the tokens are arranged in a certain order (more on this later) to make the evaluation easier.
Time for some examples. I'll start with simple examples and then introduce some more complex examples:
This is a simple example that shows you the Rules Calculator test application. The Rules Calculator allows you to create multiple tabs to run multiple expressions. I did this so that you can break down a large complicated expression into smaller expressions and evaluate the smaller expressions in their own tabs.
The Rules Basic syntax allows you to perform mathematical calculations. It allows you to do order of operations. The valid mathematical operators are:
Exponents: 5 ^ 2 = 25
Multiplication: 5 * 5 = 25
Division: 25 / 5 = 5
Modulus/Remainder: 10 % 3 = 1
Addition: 5 + 5 = 10
Subtraction: 10 - 5 = 5. The - symbol is also used to represent negative numbers. For example 1+-1=0
Of course, the Rules Basic syntax also allows for logical and Boolean operators:
Less than
Less than or equal to
Greater than
Greater than or equal to
Equal to
Not equal to
Logical and
Logical or
The Evaluation Engine allows you to perform mathematical calculations, string manipulations, date calculations, and Boolean logical. Operand functions can be embedded within Operand functions (within operand functions....). Mathematical expressions (with order of operation) can be embedded within operand functions. In the example below, notice that mathematical expression is embedded within operand functions which are embedded in other operand function and compared against the integer value 2000:
Here's another simple example using variables. After you parse the Rules Basic syntax, the Rules Calculator realizes that the expression contains variables, therefore, it automatically brings you to the variables table. You can set the value of a variable by double clicking on the variable in the list view and setting its value. After all the variables are set, you can click on the results tab and execute a "Single Evaluation". Note that you can change the values of the variables at any time and re-evaluate the result. However, anytime you change the syntax, you need to click on the "Parse" button in the main toolbar:
The evaluation engine allows you to add as much "white-space" as you need. That is, you can add tab characters and new lines; these will be ignored by the parser. Also, the Evaluation Engine supports comments. Comments are placed between ~ (tildas) and will be ignored. Note that comments can span multiple lines. Here's an example that uses assignments. Notice that the assignment operator is := and that each assignment must end with a ; (semicolon). The Rules Basic syntax dictates that the assignment declarations are made first, followed by the final expression that is evaluated. Note that the final expression that is evaluated can use any of the assigned variables. Also, assigned variables can use any previously declared assigned variables. Anything can be assigned to variables, including dates, string, numbers, Boolean, expressions, operand functions other variables, .... Here's a simple example (please read through the comments in the image for more details):
Before I continue with a final example that is more realistic, let me give you the list of operand function that I programmed in the Evaluation Engine. If you need to add your own custom operand function....it's very simple but it is a code change to the Evaluation Engine. I thought long and hard if I should make the operand function external to the Evaluation Engine so that new operand functions could be added easily. The coding of the parser and evaluator was complicated enough so I decided to program the operand function as internal methods in the Evaluation Engine. Also, I wanted the Evaluation Engine to be as fast as I could make it so I thought that internal operand functions would be faster than having the Evaluation Engine invoke methods in external assemblies using reflection. Here's the list. The "Function" toolbar button also displays this list in the Rules Calculator:
Operand Function
avg[p1, ..., pn] where p1,...,pn can be converted to doubles.
Calculates the average of a list of numbers. The list items must be able to convert to doubles.
Absolute Value
abs[p1] where p1 can be converted to a double.
Calculates the absolute value of a numeric parameter.
iif[c, a, b] where c is the condition and must evaluate to a Boolean. The value a is returned if c is true, otherwise, the value b is returned.
Performs an if-else-end
Lower Case
Converts a string to lower case
left[s, n] where s is the string and n is the number of characters
Returns the left number of characters from a string parameter.
len[a] where a is a string variable
Returns the length of a string
mid[p1, ..., pn] where p1, ..., pn are numeric values
Calculates the median for a list of numbers
right[s, n] where s is the string and n is the number of characters.
Returns the right number of characters from a string parameter
round[n, d] where n is the numeric value to be rounded, and d is the number of decimal places.
Rounds a numeric value to the number of decimal places
Square Root
sqrt[a] where a is a numeric parameter
Calculates the square root of a number.
Upper Case
Converts a string to upper case
Is Null or Empty
Indicates is the parameter is null or empty.
Is True or Null
Indicates if the parameter has the value true or is null;
Is False or Null
Indicates if the parameter has the value false or is null
Trims the spaces from the entire string
Right Trim
Trims the spaces from the right of a string
Left Trim
Trims the spaces from the left of a string
Date Add
dateadd[date, "type", amount] where date is a valid date, and type is "y", "m", "d" or "b" (representing year, month, day, or business days) and amount is an integer
Adds an amount to a date. Please note that the amount may be negative.
concat[p1, ..., pn]
This operand function concatenates the parameters together to make a string.
date[m, d, y] where m is an integer and is the month, d is an integer and is the day, and y is an integer and is the year
Create a new date data type
Right Pad
rpad[a, b, n] where a and b are string values and n is numeric. The parameter p will be appended to the right of parameter a, n times.
Pads a string on the right with new values
Left Pad
lpad[a, b, n] where a and b are string values and n is numeric. The parameter p will be appended to the left of parameter a, n times.
Pads a string on the left with new values
join[a, b1, ..., bn] where a is the delimiter and b1, ..., bn are the items to be joined.
Joins a list of items together using a delimiter
Search String
SearchString[a, n, b] where a is the string that is being searched, b is the string that is being sought, and n is the start position in a
Searches for a string within another string at a specified starting position
day[d1] where d1 is a date value
Returns the day of a date
month[d1] where d1 is a date value
Returns the month of a date
year[d1] where d1 is a date
Returns the year of a date
Sub String
SubString[s, a, b] where s is the string, a is the starting point, and b is the number of characters extracted.
Extracts a substring from a string
Numeric Max
NumericMax[p1, ..., pn]
Finds the maximum numeric value in a list
Numeric Min
NumericMin[p1, ..., pn]
Finds the numeric minimum value in a list
Date Max
datemax[d1, ..., dn] where d1, ..., dn are dates
Returns the maximum date in the list
Date Min
datemin[d1, ..., dn] where d1, ..., dn are dates.
Returns the minimum date in the list.
String Max
StringMax[p1, ..., pn]
Finds the maximum string in the list
String Min
StringMin[p1, ..., pn]
Finds the minimum string in the list
contains[p1, p2, ...., pn] If p1 is in the list p2, ..., pn, this function returns "true" otherwise, this function returns "false".
Indicates if the item is contained in the list.
between[var, val1, val2] where var, val1, and val2 are integers. if var >= val1 and var <= val2 then the function returns "true", otherwise, the function return "false".
Indicates if a value is between the other values. Please note that the comparison is inclusive.
Index Of
indexof[a, b1, ..., bn] If the list b1, ..., bn contains the value a, the index of the value is returned, otherwise, -1 is returned. Please note that this is zero based indexing
Returns the index of a list item.
now[] This operand function takes no parameters
Returns the current date
Replace[a, b, c] where a is the search string, b is the value being replaced, and c is the value that is being inserted
Replaces one string with another string
eval[r] where r is any valid Rule Basic string rule
Evaluates a Rule Basic string. I think this is an interesting operand function. In my Rules Engine, I may have rules that return a Rules Basic string. Then the result could be evaluated with this operand function. That is, have rules that create other rules. Example: eval[concat["a:=5;", "b:=6;", "a+b"]]
remove[a, b] where a and b are string
Removes the specified characters from the string
Double Quote
Returns a double quote
Proper Case
pcase[a] where a is a string
Converts a string to Proper Case. For example, the proper case of "buFFalo" "Buffalo"
Sin Wave
Calculates the sin of a number
Boolean Not
Performs a boolean Not operator on the parameter a. For example, Not[true] = false.
Is all digits
Returns true/false indicating if the parameter is all digits. For example, IsAllDigits["1234"] = true
Here's a slightly more realistic example of a rule that may be used by an insurance company to calculate the monthly payment of a life insurance policy. Here are the business rules for this life insurance policy:
The Rules Basic syntax for the above logic is saved in the file "InsPolicyA.rule". You can open this file in the Rules Calculator, set the values for the age, smoker, and weight and run the by clicking on the "Single Evaluate" button in the result tab. The final payment is calculate and returned as a string, such as "Monthly Payment = $374.00 (USD)".
Rules Engines are very powerful. In the above example, we have a complicated rule to calculate a customer's monthly payment for a product. A real insurance company probably has hundreds of products that all have special business rules. A financial institution, may have hundreds of products a customer can qualify for. A shipping company may have a set of business rules that dictate when items get shipped or re-ordered. If business rules are housed in a central location, administration of the rules becomes easier. If a rule changes, there is only one location to change the rules instead of all the client applications that embedded the rules in their logic. Also, if the Rules Engine is running on a Rules Server, there are additional benefits to be gained such as scalability, fault tolerance, and performs gains.
Creating a client application to consume the Evaluation Engine is a simple process. There are only 2 objects involved:
In the above insurance example, how could we evaluate that rule using a custom designed client? Here's a small console application that will load the rule, set the values for the variables and return the results:
// create the token object from the .Rule file EvaluationEngine.Parser.Token token = new EvaluationEngine.Parser.Token( new System.IO.FileInfo("InsPolicyA.rule")); // set the values for the variables token.Variables["Age"].VariableValue = "38"; token.Variables["Smoker"].VariableValue = "false"; token.Variables["Weight"].VariableValue = "175"; // create the evaluator object and pass in the token object in the constructor EvaluationEngine.Evaluate.Evaluator eval = new EvaluationEngine.Evaluate.Evaluator(token); // run the evaluation string ErrorMsg = ""; string result = ""; if (eval.Evaluate(out result, out ErrorMsg) == true) Console.WriteLine(result);
The download files contain a sample client console application. Here's a screen shot from that application:
Assume that you create some rules with the Rules Calculator and you save the rules into .Rule files. Some of the variables that you have defined can be found in multiple rules. For example, consider the Insurance company again. We created a rule to see if a customer qualifies for a life insurance policy and that rules takes 3 parameters: age, smoker, and weight. The insurance company could also have another rule that provides rate quotes for car insurance. This car insurance rate quote rule could take 3 parameters: age, smoker, and gender. Therefore, amoung the 2 rules (Life Insurance Policy and Car Insurance) there are 4 parameters: age, smoker, weight, and gender. If we have these 4 parameters for a customer, it would be nice to run both rules. That's were the EvaluationEngine.Parser.TokenGroup object is used.
The Rules Calculator provides an implementation of the TokenGroup object. To add a new rule group in the Rules Calculator test application, click on the "Rule Group" in the drop down menu item:
This will create a new tab and load the Rule Group interface.
You cannot create a new rule in the Rule Group interface; You can only open saved .Rule files. Click on the "Open" toolbar button and open multiple .Rule files. After you have the Rules open, set the values for the variables by double clicking on the variables and setting their values. Finally, click on the "Parse" button in the main toolbar to execute all the rules. The results of the individual rules are displayed in the "Results" column of the List View.
If you look at the source code, you will notice that I put a lot of comments in the code. The Evaluation Engine code has two major pieces: Parser and Evaluator. The Parser scans the Rules Basic syntax and creates the token collection. It then sorts the token collection in Reverse Polish Notation order. Finally, the sorted token collection is passed to the Evaluator object. I will describe each of these processes in detail.
The parsing code is in the GetTokens() method of the Token object. This method starts a Do loop and begins extracting a character at a time from the RulesBasic syntax string. Each character is concatenated to a local string variable called "currentToken". Then the currentToken variable is analyzed and, depending on the analysis, a TokenItem object is created.
At any point in time, the parser knows exactly what it is looking for. For example, if the parser encounters a ~ character, it knows that it is starting a comment. Therefore, the parser knows that is can throw away (or dispose of) all of the characters it finds until the next ~ (closing comment indicator) is found. The parser manages its current state by using an enumeration (and a local variable) called ParseState. The parser only has to manage 5 states:
This state indicates that the parser is looking for an operand. Remember, the operand can be a variable, integer, string, Boolean, date, double, or null. This is the default value of the parse state; that is, the first thing the parser looks for when starting is an operand.
This indicates that the parser is looking for an operator. The operators can be mathematical, logical, or Boolean operators.
This indicates that the parser is looking for a double quote. Typically, when the closing quote is found a TokenItem object is created and set to data type string.
This indicates that the parser has found a valid operand function and is parsing the parameters of the operand function. You will notice in the code that multiple parse states are maintained. For example, the current parse state indicates that we are parsing an operand function. However, a separate parse state is maintained to parser the parameters of the operand function. A separate parse state is needed for the parameters because the parameters to a operand function can also be valid expressions.
This parse state indicates that we are in a comment. Any characters that are encountered while in "comment-mode" are ignored. The parser is scanning the characters and looking for the ending comment indicator.
Now, with the help of parse state, the parser knows what it is looking for. For example, if the parser is looking for an operand and it encounters a "+" character (that is, it is looking for an operand and it finds an operator character), there may be a problem with the syntax since "+" characters are not allowed in operands. The point is that the parser knows what it is looking for and, of equal importance, it knows what it is looking for next. That is, if the parser is looking for an operand, then it knows that it will be looking for an operator next (or the end of the Rules Basic syntax).
There's a lot of code in the GetTokens() method so it's hard to detail it all in this article (I put a lot of comments in the code to help you understand what the parser is doing). After the parser extracts a character, you will see some nested switch statements and switch statements with log if-elseif statements. This is how I programmed the parser to know what it is currently looking for and what it is looking for next. Here's some code from GetTokens() with some detail around the space and comma handling. Notice that the switch statement looks at the current parse state. In the code sample below, if we are looking for a operand and we find a space, a token is created and the next parse state is set to look for a operator. Similarly, if we are looking for an operand and we find a comma and error is returned.
switch (parseState) { case ParseState.Parse_State_Operand: #region Parse_State_Operand if (c == '"') { .... } else if (c == ' ') { #region Space Handling try { // we are looking for an operand and we found a space. // We are not currently looking for a closing quote. // Assume that the space indicates that the operand is completed // and we now need to look for an operator tokenCreated = CreateTokenItem(currentToken, false, false, out tempParseState, out isError, out lastErrorMessage); if (isError) return; if (tokenCreated == true) { // set the next parse state parseState = tempParseState; // reset the token currentToken = ""; } } catch (Exception err) { lastErrorMessage = "Error in GetTokens() in Operand Space Handling: " + err.Message; return; } #endregion } else if (c == '(') { .... } else if (c == ')') { .... } else if (c == '[') { .... } else if (c == ']') { .... } else if (c == ',') { // we should never be looking for an operand and find a , (comma) lastErrorMessage = "Error in Rule Syntax: Found a , (comma) while looking for an operand."; return; } else if (c == '-') { .... } else if (c == ':') { .... } else if (c == ';') { .... } else { .... } #endregion break; case ParseState.Parse_State_OperandFunction: #region Parse_State_Operand .... #endregion break; case ParseState.Parse_State_Operator: #region Parse_State_Operand .... #endregion break; case ParseState.Parse_State_Quote: #region Parse_State_Operand .... #endregion break; }
Creating operand tokens is a little more difficult then finding a space character and creating a operand token such as the case with this syntax: "1 + 1". It's more difficult because spaces are not required in the Rules Basic syntax. That is, "1+1" is a valid expression that does not contain any spaces. In this scenario, every time a character is appended to the string currentToken, the parser checks if the currentToken string variable contains an operator at the end. For example, when currentToken = "1+" the CreateTokenItem() method will find that the currentToken string ends with an operator. Furthermore, the CreateTokenItem() gets a little more complicated because it needs to "peek ahead". To understand what I mean, consider this example: "1>=2". Both the ">" and ">=" are valid operators. So, when the currentToken string variable is currently "1>", the CreateTokenItem() method needs to wait for the next character (the =) before the operand and operators are created. Take a look at the CreateTokenItem() to see how this is accomplished.
It's really easy for a human to look at the math expression "1 + 2 * 3" and know that the answer is 7 (using order of operations). It's difficult for a computer to evaluate this same expression. The computer needs to re-arrange the items/tokens in the expression so that it's easier to evaluate. In fact, the computer algorithm should re-arrange the expression so that it reads "2 3 * 1 +". This tells the computer that 2 and 3 need to be multiplied first and then 1 needs to be added to the result. The human notation "1 + 2 * 3" is known as Infix notation and the sorted computer notation "2 3 * 1 +" is known as Reverse Polish Notation (RPN). A computer can easily evaluate RPN simply by pushing and popping items from a Stack Abstract Data Type. Here's the simple algorithm for evaluation RPN:
In our simple example, "2 3 * 1 +", the 2 and 3 would be pushed to the stack. Then the 2 and 3 would be popped from the stack and multiplied. The result 6 would be pushed back on the stack. Next, 1 would be pushed on the stack. Final, 6 and 1 would be popped off the stack, then added together, and 7 would be pushed back on the stack. That is our final answer.
Obviously, this is a huge over simplification. The Evaluation Engine has to deal with operand functions, order of operations, variables, variable assignment, and so on. Fortunately, there is a famous computer scientist that invented an algorithm to convert from Infix notation to Reverse Polish Notation. This algorithm is called the Dijkstra Shunting Yard algorithm. More information about the algorithm can be found on Wikipedia at http://en.wikipedia.org/wiki/Shunting_yard_algorithm My implementation of the Shunting Yard algorithm can be found in the Token.MakeRPNQueue() method. The Rules Calculator displays the RPN for each expression in the "RPN Tokens" tab. For example, the RPN for (1 + 2) * 3 is
Notice that the parenthesis for (1 + 2) * 3 disappear in the RPN list. That's because the RPN sort the tokens in such a way that parenthesis are no longer needed. The order of operations in an RPN stack is accomplished by the sort order. Again, please review the Token.MakeRPNQueue() method if you want details on the sorting algorithm.
In the last part of this article, I would like to go through the exercise of adding a new Operand Function to the Evaluation Engine. Let's add the trigonometry function Cosine to the Evaluation Engine. The Cosine Operand function will take 1 numeric parameter. Here's the steps involved to add the new Operand Function:
public static string[] OperandFunctions = { ..., "cos" };
case "cos[": try { success = Cos(Parameters, out Result, out ErrorMsg); } catch (Exception err) { ErrorMsg = "Failed to evaluate the operand function " + OperandFunction.TokenName.Trim().ToLower() + ": " + err.Message; success = false; } break;
private bool Cos(Parser.TokenItems Parameters, out Parser.TokenItem Result, out string ErrorMsg) { // initialize the outgoing variables ErrorMsg = ""; Result = null; // make sure we have at least 1 parameter if (Parameters.Count != 1) { ErrorMsg = "Error in operand function Cos[]: Operand Function requires 1 parameter."; return false; } // we can only take a Cos of an item that can be converted to a double if (Support.DataTypeCheck.IsDouble(Parameters[0].TokenName) == true) { double temp = Parameters[0].TokenName_Double; double cos_temp = Math.Cos(temp); Result = new Parser.TokenItem(cos_temp.ToString(), EvaluationEngine.Parser.TokenType.Token_Operand, EvaluationEngine.Parser.TokenDataType.Token_DataType_Double, false); } else { ErrorMsg = "Error in operand function Cos[]: Operand Function can only evaluate parameters that can be converted to a double."; return false; } return true; }
case "cos": Description = "Calculates the cosine of a number."; Syntax = "cos[p1] where p1 can be converted to doubles."; Example = "cos[90] < 0"; break;
That's all there is to it; you can now call the cos[] Operand Function in your Rules Basic syntax. If you add any Operand Functions to the Evaluation Engine, I would request that you post the Operand Function code and the description code to this article on Code Project and I will include the Operand Function in the original source.
Many of the business rules that I write are in the form of "if-else" statements. For example, if a customer has a certain attribute, they get a certain score. If a driver has certain driving violations, their premium goes up by X%. If a medical claim is in a certain state/condition, then delay the payment. Since many of the rules are of this "if-else" type, I have tried to optimize the iif[] operand function. Recall that the iif[] operand function takes 3 parameters: iif[c, a, b]. If the condition c evaluates to true, the result is a, otherwise, the result is b.
The formal definition of short-circuit evaluation (taken from Wikipedia) is "denotes the semantics of some boolean operators in some programming languages in which the second argument is only executed or evaluated if the first argument does not suffice to determine the value of the expression". This is nothing new to us, we have been using short-circuiting for years...take a look at the msdn help for || and see that it states: "The conditional-OR operator (||) performs a logical-OR of its bool operands, but only evaluates its second operand if necessary"
Here's how short-circuiting works in the Evaluation Engine:
The most important syntax to remember to take advantage of short-circuiting in the Evaluation Engine is do not nest the iif[] operand functions. If you do nest the iif[] functions, only the inner-most iif[] operand function will short-circuit. Instead of nesting the iif[] statements, break them into single statements and assign their result to a variable.
Here's a simple example:
score := iif[10<5, (2 + 3) * 8 + (2 ^ 4) / 6, 1];
In the above example, the condition "10<5" will evaluate to false and the interpreter will immediately jump to the last parameter and return 1. That is, the true expression (2 + 3) * 8 + (2 ^ 4) / 6 will never be evaluated, thus saving you time.
I've noticed that many mathematical evaluators that include support for "if-else" functions will evaluate all the parameters before they perform the "if-else" statement. This causes problems with certain "if-else" statements such as:
iif[x = 0, 0, 100 / x], where x is an integer variable.
In the above example, if the evaluator does not support short-circuiting and the variable x is set to 0, many evaluators will return a "division by zero" error even though the "100 / x" does not need to be evaluated. Fortunately, the short-circuiting in the Evaluation Engine prevents us from having this problem.
I'm sure there are many reasons why a developer releases his/her source code. My motivation for releasing this code is to solicit your feedback. The Evaluation Engine is an important part of a larger project that I am working on: the Rules Engine and Rules Server. If there is an error/bug in the Evaluation Engine, that error will "trickle" up to the other components that rely on the Evaluation Engine. If you like this library, please tell me. More importantly, If you don't like it, please let me know (I am open to constructive criticism). If you find a bug or have a suggestion, I would like that information too (I may make the change and re-release the code).
The Rules Calculator application uses the control from the article Enabling syntax highlighting in a RichTextBox. Thank you Patrik.
This article, along with any associated source code and files, is licensed under The Creative Commons Attribution-ShareAlike 2.5 License
if age >= 18 then ageDiscount := 1.0 else ageDiscount := 0.0 end
premium := collCost + compCost + uninsuredMotCost - (discount * customer.ageDiscount)
General News Suggestion Question Bug Answer Joke Praise Rant Admin
Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.


text:
Jewish World Review Nov. 18, 2004/ 5 Kislev, 5765
Ann Coulter The loss that keeps on giving!http://www.NewsAndOpinion.com | As we wait for CBS to concede the election, Democrats are claiming Kerry lost because Americans are stupid and if there's one thing voters respond to, it's crude insults. This is not only the first step of a brilliant strategy to win the red states back, but also inconsistent with the Democrats' theory that Bush was an illegitimate president for the last four years because Democratic voters in Florida were too dumb to follow an arrow to the circle by Al Gore's name. How stupid were the alleged Gore-supporters who couldn't figure out how to cast a vote in the 2000 election? Using classical Marxist thinking, liberals can't fathom how issues like abortion and gay marriage could trump ordinary people's economic interests which liberals axiomatically assume are furthered by the Democrats' offers of government assistance. Democrats are saying to voters: How can you be so stupid to subordinate your own selfish economic interests to "moral values," the betterment of the country and the general welfare of people you don't even know? It can only be false consciousness. If liberals think the Bush vote was composed of illiterate homophobes who fear women in the workplace, perhaps the Democrats should start demanding literacy tests to vote. Garry Wills who fills in "occupation" on his federal tax return with "self-hating Catholic" denounced America in the New York Times as an unenlightened nation full of people who believe "more fervently in the Virgin Birth than in evolution." By contrast, apparently, "enlightened" people believe in the Aborted Birth more fervently than they believe in national defense. And just in the interest of fairness here, Garry: At least there's some documentation on the Virgin Birth story. For people who believe so fervently in evolution, these Bush mandate-deniers sure are resistant to it on a personal level. On the same day, on the same nuanced Times editorial page, both Wills and Maureen Dowd wrote that Kerry was defeated by a "jihad" of Christians. The jihadists, according to Wills, were driven by "fundamentalist zeal, a rage at secularity, religious intolerance, fear of and hatred for modernity." Dowd said they were "a devoted flock of evangelicals, or 'values voters,' as they call themselves ... opposing abortion, suffocating stem-cell research and supporting a constitutional amendment against gay marriage." Finally a jihad liberals oppose! Speaking of gay marriage, as long as liberals are so big on discussing "mandates" and whether Bush has one (they say he does not), I think the one thing we can all agree on is that there is definitely a "mandate" against gay marriage. In fact, a clear majority of us are uncomfortable with the word "mandate" because it sounds like Wayne asking Stephen out for dinner and a movie.
Reacting to Bush's re-election in that calm, reasoned way we have come to expect of liberals, they are running to psychotherapists, threatening to move to Canada and warning of a fascist police state including their fear of a Hollywood "blacklist." (Now you understand how the myth of McCarthyism began, red states!) One depressed Kerry voter committed suicide at Ground Zero. Meanwhile, the entire Democratic Party is also contemplating political suicide by making Howard Dean its next chairman. Some Democrats are so despondent they've contemplated (hushed whisper) prayer. They're just not sure if they're supposed to pray to Bill Clinton or to their "Higher Power." The day after the election, documentary filmmaker and Upper West Side denizen Mitch Wood told the New York Times: "Watching my kids this morning, going down the street, flicking things in the air, jumping around, I wondered, are they going to have that sense of freedom that I had growing up?" As if on cue, a commercial jetliner piloted by Islamofascist hijackers did NOT crash in front of Wood at this point, killing his entire family instantly, in silent testimony to the national security we currently enjoy under President Bush. Wood gave no indication of noticing this. A teacher on the Upper West Side, Ireena Gurvich, said, "I'm thinking of leaving the country." Gurvich said she wanted to go to Canada because, "it's a kinder and gentler United States." And yet you still ask why our children cannot read or write. Another denizen of the Upper West Side, Patty Fondrie, said: "If it gets bad, we'll go to France," where she will probably be murdered by Muslims. Michael Conway, an administrator at United Talent Agency in Beverly Hills, Calif., was quoted in the Times worrying, "What's going to happen, some kind of blacklist?" suggesting an entirely new, if somewhat scatological connotation, to the term "A-list." I think we have a long way to go from Michael Moore being an honored guest at the Democratic National Convention to a "blacklist" except for actors who believe abortion and gay marriage are "wrong." But here's hoping.
Every weekday JewishWorldReview.com publishes what many in Washington and in the media consider "must reading." Sign up for the daily JWR update. It's free. Just click here.
JWR contributor Ann Coulter is the author of, most recently, "How to Talk to a Liberal (If You Must) : The World According to Ann Coulter". (Sales help fund JWR.)

subset: commoncrawl


text:
Video now accounts for half of all data transferred on mobile networks, up from 40% during the same time last year, according to ByteMobile's first quarter 2012 Mobile Analytics Report.
Where is the video growth coming from? Increased use of tablets, more support for HD video etc?
On certain mobile networks, video can account for up to 69% of traffic, ByteMobile found in its quarterly survey of 3G and 4G mobile networks that use ByteMobile's network management tool, SmartCapacity.
READ: Is smaller better for iPad size? Two gadget repair gurus weigh in
SLIDESHOW: A look at tablets, great and small
Smartphone and tablet users are driving the increased video volumes, as is the rise of full-length and studio-quality videos, live streaming of multimedia content and two-way video communication.
"The widespread use of smartphones, tablets and other high-end mobile devices - combined with the explosion of rich media and the delivery of applications over the web − has driven network data traffic volume to new heights," says Stacey Infantino, of ByteMobile. "With 2G and 3G networks giving way to 4G networks − fueling mobile subscriber appetites for high-definition video, streaming media, on-demand movies, and more − network capacity has become a business challenge for mobile network operators (MNOs)."
Diving into the specific findings in the study, ByteMobile found that volume increases substantially based on video resolution. For example, while a five minute 360p video, which accounts for the majority of mobile video traffic, creates 10M to 15MB of data, a high definition video can create five times as much data, or 75MB, the study found.
Tablets also generally create more data than smartphones, ByteMobile found. Android tablets create twice as much data compared to Android-based smartphones, and iPads create three times as much data as iPhones, the study reports.
In terms of advertising-related traffic, Android-based devices create more transactions compared to iOS and Google's advertising services, including DoubleClick, AdMob and AdSense, generate 75% of data produced by advertisements. Meanwhile, Apple's iAd generates higher data per transaction, a finding ByteMobile said points to the "richer media content" found in iAd promotions.
As for social networking, Facebook is where users spend the most amount of their time. Each Facebook session lasts an average of 9.06 minutes, while users spent an average of 8.51 minutes on YouTube and 4.57 minutes per session on Twitter. Even though YouTube sessions are on average shorter, they create 350 times the amount of data (40MB) per session compared to Facebook (120KB), emphasizing the data-rich content of videos.
For the full results of the study, click here.
Network World staff writer Brandon Butler covers cloud computing and social media. He can be reached at firstname.lastname@example.com and found on Twitter at @BButlerNWW.
Read more about anti-malware in Network World's Anti-malware section.


text:
When I think back on 2009, I feel the same pleasant discomfort you get at the end of a John Hughes movie, when suddenly all the jocks and dorks and punks are good friends. This year, hardcore denizens of time-worn niches came out of hiding and acted all presentable — I mean, the Pixies played the Wang — and all sorts of scenes and sounds went behind the bleachers for some unlikely scores. The following tracks from local newbs and well-aged vets alike almost all stepped out of the shadows in 2009 with that knowing, Judd-Nelson-on-a-football-field look. You know the one.
• Passion Pit, "The Reeling"No one else in town nailed it quite the way Passion Pit did with their debut, Manners (Frenchkiss). Michael Angelakos and company represent some of the best parts of Boston's web of dance nights, laptop DJs, and bedroom studios, a web that's led to recent crossover projects like Bodega Girls and the Coralcola/Big Digits team-up. Thus far, however, "The Reeling" has no match for pure bravado. It's not just anyone who can take a helium-voiced call-and-response and graft it to a glitchy synth bass line with positive results. And Passion Pit shoot the moon by adding Miami Vice drum fills and a Bee Gees disco groove that defies everything you thought you knew about stoic Boston-rock archetypes.
• Hallelujah the Hills, "Paper Pilots"I've got a hoard of old Ryan Walsh four-track demos that I'll never give up. Like, "Limited Edition 2 of 3" stuff, full of amazing hiss and edits that drop with heavy tapehead clunks. This year finally brought us a start-to-finish studio record. "Paper Pilots" closes out the epic Colonial Drones (Misra) with the most victorious death knell ever recorded. It all comes down to the final minute, where Walsh and the band trade in their signature kitchen-sink approach for a blunt two-chord fuzz: "You're gonna live/I'm gonna die" takes the nightmare insecurity and the vague conspiracies and mops them up into one satisfyingly sure thing.
• General Interest "Capricious Youth"Who could complain about Conversions being gone when an outfit like this rises out of the ashes? Boston's own Ride the Snake label — home to Life Partners, Reports, and Dead at 24 — released this nugget on General Interest's Rightby the Beach 12-inch. Erase Errata bass punch and old Ex-Models guitar stabs are the weapons of choice as the band step all over some otherwise perfectly grimy punk territory. "Capricious youth/Oh, I don't know/Capricious youth/Life is confusing" are among the lyrical bon mots thrown out here by Steve Shea — with the moral fortitude of a young Rodney Anonymous.
• Converge, "Dark Horse"It's been a while since you could spazz out to a Converge song on the first try — theirs is expert-level stuff. But this year, they dropped "Dark Horse" to lead off their ferocious Axe to Fall (Epitaph), and now that there seems to be a common thread between this band and other human beings, you have to start thinking about them a little differently. Yes, they remain brutal, but they now feature all sorts of guilty pleasures, like Super NES quest-metal guitar lines and garage-punk pick slides. The new attitude seems to be working: they started the year off in the sweaty nook of the ICC in Allston and closed it out opening for the Cartoon Network's Dethklok at the House of Blues.
See all articles by: MATT PARISH
All Slideshows


text:
There is currently a lively, spirited debate about the forthcoming user experience changes for Drupal 7. A quick summary for those who have been unaware of this initiative: everyone (yes, especially you) needs to go to http://www.d7ux.org/ and actively participate in the discussion/brainstorming/wireframing/etc. in order to ensure that the end result is something we can all be proud of and meets our community's very diverse needs!
It's been interesting to watch the range of opinions expressed in the thread. On the one side you have people who have first-hand experience with how excruciatingly painful the learning curve can be for new users, either because they themselves had to wrestle for weeks about menus vs. taxonomy vs. nodes, or because they've spent time around others (co-workers, clients, spouses, etc.) and have watched them struggle. They're very excited about the prospect of some of these pervasive user experience issues being looked at in a very serious way. On the other side you have long-time members of the community, many of them prolific contributors, who are adept ninjas configuring Drupal sites. They don't want to see Drupal "dumbed down" to the lowest common denominator. In fact, the whole reason they initially chose and continue to stick with Drupal is the sheer power it places into their hands, and with great power comes a learning curve; it's to be expected.
At my "day job" at Lullabot, we've been hard at work on the Drupal UE (Usability Edition), which includes many fine improvements that I'd love to see make their way into Drupal 7. But what about our roots, the hardcore developers who eat, sleep, and breathe Drupal? Who is watching out for their interests?
In a fit of insomnia early this morning, I put together what I hope will be the start of a robust framework that optimizes Drupal's UX, but this time for the developer. I call it Better Admin module.
When you enable the Better Admin module (for Drupal 7 only, download it here), your Drupal interface immediately turns into this highly optimized view for power users:
All the power of Drush, right within your Drupal website! Let's take a look at some of its currently implemented features:
- Navigate to any page in Drupal NOT by typing the URL in your browser address bar as you'd normally have to do (or, heaven forbid, drilling down the navigation menu), but with the convenient
goto url
command! - Login and log out with ease! No more hunting around to find links in whatever silly navigation menu a "normal" site might put them in. Simply enter the commands
login username password
, respectively. - A robust and powerful help system is at your fingertips with the illustrious
command. - The only way to uninstall it is to delete the betteradmin row in your system table and rebuild the registry cache!
- And so much more!
Who's with me?!
This is a major leap forward Drupal administer / developer's experience. With this module, and little bit of hacking, I'll soon be able to get rid of my mouse once and for all. That's right, no more clicking or searching through walls of text. This has the potential to really bring the power of the command line to the admin experience, which statistically is the most frequent feature request, IMHO.
Better Admin module is full of win.
My uncle is providing
My uncle is providing Canadian immigration consultancy services to various clients world-wide and he has asked me to help (he couldn't get me the immigration though). Currently it is all being done MANUALLY or through emails. The process is simple, receive CV's, get initial assessment, inform clients about updates, ask them to make fee payments at various stages and commission.
( BSC Dissertation , Defense Dissertation and Dissertation )
I just have to say this...
I don't think you've gone far enough. What is this typing a command silliness? If we're admins we should knowing the machine we're using. We should be writing machine code to update the database.
Think of the fun, having to find the spot on the disk where the DB is storing a field and updating that field using only 1s and 0s. Real programmers only need those 2 characters on their keyboard.
i .. uh ...
i actually want this.
At least the "module enable drush" / "module disable blocks" browser-based command line option...
An ASCII art Drupal!! You are so hard-core!
Forget typing. I want the ESP version that just *knows* what I want to do :-)
Not too long ago I saw this
Not too long ago I saw this article about a brain scanner that types what you're thinking... you might show this up at your local computer store sooner than you think ;)
Drupal 7 Only?
I desperately need this for D5... any idea if a backport in the works?
feature request
submit button? with rounded corners? you can't be serious..
April 1st?
I was busy the other day so I didn't have time to catch up all the April 1st blogs. This one is pretty funny. And I did checkout the code:
switch ($cmd) {
case 'help':
case 'wtf':
return 'Help is for wuss bags! Use the source, Luke!';
case 'goto':
if (isset($args[0])) {
else {
return 'Usage: "goto admin/build/modules"';
case 'module':
if (isset($args[1])) {
if ($args[0] == 'enable') {
elseif ($args[0] == 'disable') {
else {
return 'Usage: "module enable poll" or "module disable forum"';
case 'node':
if (isset($args[0]) && isset($args[1])) {
// TODO: Ran out of time.
else {
return 'Usage: "node view 12" or "node add type [My post here]"';
case 'login':
if (isset($args[0]) && isset($args[1])) {
user_authenticate(array('name' => $args[0], 'pass' => $args[1]));
else {
return 'Usage: "login username password"';
case 'logout':
case '':
return 'Huh?? What the heck are you saying?';
And I actually tested with a drupal 7/sqlite setting. It worked!
Now seriously, as a post on April 3rd, I think there might be something useful here. In terms of admin efficiency, nothing beats the shell and man page in UNIX. Since documentation is important and busy admins have no time to look into the source code, I suggest the drupal 7 core team add a "man page" feature for all core modules, if there is more time, perhaps a hyperlink GNU Texinfo version as well.
Thank you for the nice work.
thanks for sharing this
thanks for sharing this really interesting post.
I just need your 5 minutes
Hi Angie,
First of all many thanks for all your support on Drupal, videos and modules. I don't know how to contact you (all contact forms disabled every where)...
Please just guide me with just the names of the modules for the below requirements and i will figure out the rest.
(and please un-publish my comment from this post :S)
My uncle is providing Canadian immigration consultancy services to various clients world-wide and he has asked me to help (he couldn't get me the immigration though). Currently it is all being done MANUALLY or through emails. The process is simple, receive CV's, get initial assessment, inform clients about updates, ask them to make fee payments at various stages and commission.
First of all, he is short on budget, have very limited or almost no technical team on board except myself with LITTLE BIT know how of DRUPAL.
The requirements are as follows:
1. People contact us and we tell them to visit our site to get detailed information on services that we provide
2. People visit our site and browse through the information & immigration categories that we are offering services for
3. People decide what category they would want to apply for and click on "Apply for immigration button"
4. They will be presented with a CV submit / upload form or choose to create their CV profile with us
5. After creating CV profile or uploading their CV file OR FILL A FORM ONLINE, they will be asked to register to confirm their submission (Name, Email, Phone number)
6. Our team get notified for submissions, they review consult or do the necessary to evaluate their CVs
7. User get notified at each step when his CV was reviewed and what is the status
8. User get notified if his application was approved or rejected by authorities
9. Upon approval, user gets an option to make the first installment of payment
10. Repeat 5-9 until his final visa and settlement
Please HELP me I really am in the middle of of the drupal learning curve...
Thank you and best regards
Awesome, looks pretty promising. I like Drush so I'll have to give this a go.


text:
Photo Credit: Imagens Cristãs |
While it is true that many of us are rightly concerned about churches getting kicked out of NYC public schools, government requirements regarding health care and contraception, and campus groups losing their charters on college campuses because of their beliefs, we must also realize that many of our brothers and sisters in other places are facing far greater challenges.
Even with the appearance of the lack of concern for the rights of Christians in the U.S., the treatment of Christians in my home country is far from the worst in the world. In a recent Newsweek cover story, Ayaan Hirsi Ali sheds some light on what is happening to some Christians in other parts of the world:
"We hear so often about Muslims as victims of abuse in the West and combatants in the Arab Spring's fight against tyranny. But, in fact, a wholly different kind of war is underway—an unrecognized battle costing thousands of lives. Christians are being killed in the Islamic world because of their religion. It is a rising genocide that ought to provoke global alarm.
The portrayal of Muslims as victims or heroes is at best partially accurate. In recent years the violent oppression of Christian minorities has become the norm in Muslim-majority nations stretching from West Africa and the Middle East to South Asia and Oceania. In some countries it is governments and their agents that have burned churches and imprisoned parishioners. In others, rebel groups and vigilantes have taken matters into their own hands, murdering Christians and driving them from regions where their roots go back centuries.
The media's reticence on the subject no doubt has several sources. One may be fear of provoking additional violence. Another is most likely the influence of lobbying groups such as the Organization of Islamic Cooperation—a kind of United Nations of Islam centered in Saudi Arabia—and the Council on American-Islamic Relations. Over the past decade, these and similar groups have been remarkably successful in persuading leading public figures and journalists in the West to think of each and every example of perceived anti-Muslim discrimination as an expression of a systematic and sinister derangement called "Islamophobia"—a term that is meant to elicit the same moral disapproval as xenophobia or homophobia.
But a fair-minded assessment of recent events and trends leads to the conclusion that the scale and severity of Islamophobia pales in comparison with the bloody Christophobia currently coursing through Muslim-majority nations from one end of the globe to the other. The conspiracy of silence surrounding this violent expression of religious intolerance has to stop. Nothing less than the fate of Christianity—and ultimately of all religious minorities—in the Islamic world is at stake."While it is true that Christians should be concerned about the mistreatment of any persons no matter what faith they subscribe to, we mustn't minimize the very real suffering and persecution that Christians around the world face everyday -- whether the mainstream media covers it or not. Kudos to Newsweek for bringing further attention to this matter.
To read the rest of the article please click here.


text:
Industry standards body VESA has officially updated its DisplayPort Dual-Mode 1.1 standard to provide better performance, higher resolutions and increased interoperability when hooking up to HDMI and DVI ports through a cable or adapter. Under Dual-Mode, a DisplayPort can output an additional HDMI/DVI-compatible signal alongside its expected DisplayPort link. This allows for connectivity to HDMI and DVI-equipped devices without the need for cables or converters equipped with active electronics.
Current DisplayPort Dual-Mode converters/adapters suffer from a limited output of 1080p @ 60Hz with 24-bit color. VESA's update includes support for just about anything HDMI 1.4 can handle – deep-color, 3D 1080p @ 60Hz and 4K UHD (2160p) @ 30Hz – but all through a single cable. These improvements are achieved by nearly doubling the TMDS (Transitional-Minimized Differential Signal) rate from 165MHz to 300MHz.
It's worth noting the current DisplayPort standard (pdf) itself has no trouble delivering 4K UHD signals @ 60Hz and 24-bit color.
DisplayPort adapters and cables which meet the new specifications will be referred to as "Type 2". Previous-generation devices, cables and adapters will be henceforce labeled as "Type 1". Type 2 (300MHz) adapters will be compatible with existing 165MHz Type 1 source devices, but the performance of such adapters are downgraded to 165MHz for compatibility. However, in some cases, a software update may allow existing Type 1 devices to take full advantage of Type 2 features and performance.
The updated standard comes at an auspicious time when ultra high-def displays are are clearly on the way. If CES is any indication (and it likely is), 4K UHD and even 8K UHD televisions and displays are imminent. Japan's government seems to agree with that assessment.


text:
As her second birthday draws near in the next few weeks, I have been thinking about how much has changed since her first birthday (see my two lists of firsts before then). She is no longer a little baby. She runs when she wants to get somewhere and tells me what she wants (bikkies!).
Today we saw a dietician as part of a routine medical appointment. It was a relief to finally speak to someone who could talk to me reasonably about a child's vegetarian diet and be reassured that her iron intake seems fine without needing supplements, though I was recommended to put her on calcium supplements because she is not keen on dairy products (or fortified vegan alternatives). So I feel reassured
- had her first taste of tomato sauce with her vegetarian sausages this week
- usually has a breakfast of cereal, toast with promite and cheese, and a piece of fruit - if she eats it all
- loves spicy food - is quite partial to curried chickpeas
- often has plain veg with plain beans or tofu for dinner
- sometimes loves baked beans and sometimes hates them
- loves to explore the kitchen drawers
- when she is distracted from eating dinner she says "fitty" (finished) and push her plate away - it doesn't always mean she really has finished
- will not drink milk or eat yoghurt but she loves cheese
- loves to drink water but can't resist sprinkling it everywhere if I turn my back for a moment
- is hard to please when eating out unless I buy her something from a select group of favourite foods - chips, margharita pizza, falafels and cheeseymite scrolls
- can say the name of most of her food and if she doesn't know she can ask "what's dat?"
- loves to pretend she is cooking outside with her little pots and bowls - this usually involves water and sometimes sand pies
- "cuggles" dolly, who must come everywhere
- is fascinated by the moon and loves us reading her Where the Wild Things Are because the moon is on almost every page
- is careful with Zinckie cat and pats her gently now though she does love to stick her face close to Zinc's to tell her something and expects her to play logo and eat cherries with her
- loves singing songs - at the moment her favourite seems to be "happy birthcake to oo" - but if we join in we get told very sternly, "sylvia sing"
- plays with my purse if she can get away with it - but I was pleased to find her putting a stray coin in it this week rather than just throwing my money away
- can reach the railing by the steps outside the back door
- is constantly losing things - our house has never been the same since she became mobile
- prefers to climb in and out of her stroller by herself
- giggles when she is jumping up and down
- looks out for the cockatoos on the neighbouring tree that we can see from our backyard
- know that Zinc goes off on a run each night but not where - last night she guessed that Zinc had gone shopping at the supermarket
- is amused by my vegetable flowers that I make to encourage her to eat vegetables but also because I love playing with food
The recipe was inspired by Jacqueline's chickpea and coriander patties that she made for her little boy, Cooper. I made quite a few changes because I had a sourdough loaf to make into breadcrumbs, I don't like fresh coriander and I thought an egg would add a bit more nutrients. They were good everyday food that E and I enjoyed but Sylvia wasn't that keen.
More successful were my recent attempts at cheeseymite scrolls. I had been inspired by Lisa's recipe as part of her great Australia Day recipes series. I have also seen similar scrolls or pinwheels on Should You Eat That and always meant to try it. Now that I am on a scroll roll (ha ha) it was on the cards.
The reason I wanted to try the puff pastry cheeseymites was when faced with paying out for scrolls for everyone on the weekend at Bakers Delight. For those that don't know the BD franchise, cheeseymite scrolls are one of their regular items, bread dough rolled up with vegemite and grated cheese inside. (A photo of these scrolls is the fourth photo down from the top of the post.) I buy them often but when everyone in the house wants them the price adds up.
Then I remembered seeing Lisa making them. They were so simple and quick to make. Sylvia couldn't get enough of them - not even after they had sat in the bikkie tin over night. I used promite instead of vegemite and used up some old sheets of puff pastry in the freezer. I often have puff pastry leftover so this is an excellent recipe to use it up. They are smaller and richer than their bready cousins but they taste so delicious. Maybe another batch will be made on Sylvia's birthday!
Previously on Green Gourmet Giraffe:
This time last year: More baby food, more healthy muffins
This time two years ago: WTSIM … Fruit kebabs
This time three years ago: PGermy Bran Muffins
Cheeseymite puffs
makes about 8-10 puffs per sheet of puff pastry
puff pastry sheets
promite or vegemite
grated cheese
Defrost puff pastry sheet. Spread with promite and sprinkle with grated cheese. Roll up and cut into 1-2cm slices. Arrange on a lined baking tray and bake at 220 C for 15 minutes or until golden brown.
Curried Chickpea Burgers
made 13
400g tin of chickpeas, rinsed and drained
150g dried breadcrumbs
1 red onion, quartered
1/4 cup buttermilk
1 egg
1 tsp curry powder
oil spray (or olive oil)
Place chickpeas, breadcrumbs, red onion, buttermilk, egg and curry powder in food processor and processor til it all comes together. Form mixture into small patties. Heat a non stick frypan and spray with oil spray or pour in a glug of olive oil. Fry patties over medium heat for a few minutes either side. Cook in oven for about 20-30 minutes (mine was on the bottom of the oven for about 30 minutes). Serve warm with relish.
On the stereo


text:
LTY UPDATE: Friday, September 14th, 2012
Asanvari Bay, Maewo Island, Vanuatu
LTY time: 17:05 (Vanuatu time = UTC +11)
Location: Asanvari Bay, SW tip of Maewo Island, Vanuatu
Position: 15 22.505 S, 168 08.020 E (you can cut & past this into Google Earth to see on map)
Wind: 50-20 knots (inside the bay)
Seas/Swell: flat
Air temp: 82 F 28C
Sea temp: 90.5 F 32.5 C
Barometer: 1017mm
AWEMAZING DAY in ASANVARI BAY
I awoke as usual to first light this morning and enjoyed watching the sky brighten gradually to bright blue as I lay there looking up through the large hatch directly above my aft cabin bed. I have a similar view of the night sky each evening when I go to bed and so my days start and end with these vivid reminders of just how fortunate I am and how amazing the cosmos is. Just as the changing hues and brightness told me that the sun had just peaked above the horizon I heard some odd splashes and the sounds of young voices followed by some slapping on the aft transom steps directly behind my head on the bed. In many ways I've learned that you sail by sounds and you get to know each and every one of the thousands of different sounds on the boat and know when something changes or there is a new sound. I hadn't heard this symphony of sounds for some time but I knew just what it was; my first visitors of the day had arrived!
I'm starting to get used to it but it is still an odd feeling when I first come up on deck each morning and find a whole group of people already sitting on the beach looking out at Learnativity and waiting for me to rise. As soon as I'm spotted on deck the calls, whistles and shouts begin as they try to get my attention and it happens throughout the day and right into the evening in many places. I guess it is partly because wherever possible I seek out small little bays or anchorages that are not charted or popularly promoted in the sailing guides and so I am often the first boat and "white man" they have seen in quite a while. Then as soon as my first visitors discover Ruby and that I'm quite happy to host them onboard, show them around and answer their questions, it seems that more people that I could ever imagine were living ashore come out of the jungle. It is a school holiday for two weeks right now and so there are more children around with all day to do as they please so there has been a particularly large number of them aboard the past few weeks.
As I mentioned in yesterday's post I took a group of about ten boys for a ride with Ruby and I in the dinghy and had a few more of them onboard so word was out that this new boat in the bay was "visitor friendly" and the procession began early. Apparently their enthusiasm got the better of some of the braver ones this morning and they just couldn't wait for me to be sighted so about six of them swam the 100 meters out to Learnativity "just in case" I was up before six today. It is such an amazing sight that brings such a smile to my face as I step out onto the aft deck and see six young glistening brown bodies hanging on and peering up at me from the bottom swim step, laughing excitedly and sounding like a bunch of young school girls even though these are almost always young boys ranging from about five to twenty years. So that's how my day started and the procession of visitors from ashore continued for the next two hours and I think I must have had well over thirty of them onboard in groups of four to ten. I was just going to do a short sail of about 15nm up to Asanvari Bay today so I didn't have to rush to get away and just reveled in the joy and laughter with all my new found Ni Vanuatu friends. (this is how the people of Vanuatu refer to themselves).
Not a bad "commute"! How was yours?? ;)
Once the swimmers had all been out to see me I got things stowed away, raised the anchor and was sailing out of Namaram Bay by about 09:30. The weather was perfect with clear skies and calm seas and although there was no visible wind off to the west of Pentecost I was reasonably sure I'd pick it up once I got up to the north end and out in the pass between Pentecost and Maewo islands. Almost as if I knew what I was doing this is exactly what happened as the wind continued to build as I sailed north and I was soon doing over 7 knots with the full main and genoa out to Port as the SE trades blew through at 1-20+ knots. It was only 15nm up to Asanvari Bay which is on the very SW tip of the long skinny N/S running Maewo Island and I had the anchor down by just after noon.
Asanvari had come highly recommended by Philip and Teri who had been here a few weeks ago and just loved it and I've read that every boat that has been here has raved about it. You never know just how a spot is going to strike you though as we are all so different, but this spot is right out of a movie set or poster and is just the most perfectly pristine little tropical jewel I've seen in a long, long time. Funny how life works as I found myself thinking over the past few days how Vanuatu was very beautiful and the people most interesting but didn't create the same degree of awe and amazement in me that Fiji did. Then I sailed into Asanvari Bay. If you get the chance do check this location out on Google Earth or Bing as I'm certainly not able to do it much justice with my impoverished prose though I think it would be a challenge for even great writers. I've taken lots of photos and videos already and whenever I get a good internet connection, maybe as soon as next week, I will post my backlog of photos up on the blog so you can get a much better idea of just what I've been experiencing lately.
Asanvari Bay is a very small arch cut into the SW corner of Maewo Island with a protruding finger of rock and coral creating a small west pointing finger at the south end and then curving in an arc that is probably no more than 2km long along the coastline. At the south end of this little bay there is a white sand beach with about ten or so huts and houses and the villagers I met there this afternoon tell me there is another small village a few hundred yards east on the other side of the point. Unlike Namaram Bay I did not see a single soul ashore for the longest time and then only a few young boys out in their dugout outriggers and maybe three adults ashore. As the shore curves around to the north it goes back to being craggy black volcanic rock until it reaches a large stream that enters the bay and a cascading waterfall set just back into the island that you think must be a mirage it is so beautiful and picture perfect. The shoreline continues on the shallow arch around to the north and changes to steep sided cliffs that have risen up out of the water with some underground forces and comes complete with a tiny cave that I am anchored right in front of. As the arch finishes its curve north there is another beach, this one of highly polished black volcanic stones sprinkled with white shards of dead coral that has washed ashore.
On my visit there this afternoon I met Jason, a man of about 40 I would guess who lives in one of the two small houses there and amongst a large and very fertile plantation behind his house he has two pigs who get their own beachfront palm oasis and seem to enjoy a steady supply of coconuts based on the thick carpet of coconut husks they were sleeping on. Ruby did her best to get them to play with her and they seemed amused by this strange little critter but weren't up for any games.
I made a brief stop at the waterfall on my slow trip around the bay in the dinghy and someone has gone to a lot of trouble to pour a very substantial concrete sea wall and erect a small little "bar" building complete with stools. However the waterfall itself is Mother Nature at her best and so I just stood in about two feet of this clear fresh water that had just crashed down the rock face of the waterfall above. I'll go back in tomorrow as the elderly man and woman there said I'd be welcome to come back for a shower and/or to wash my clothes. Now THAT is my kind of shower and laundry facility!!
I could go on and tell you how clear the sea water is, how there was a steady flow of the most beautiful little black and white birds putting on the most amazing aeronautical acrobatic show as they zoomed through the moist air just in front of the waterfall, but I'll leave it at that and the pictures to follow for now. Suffice it to say that as I try to comprehend how just this one day has started and ended I think you can appreciate why I keep repeating and appreciating just how fortunate I am. As with today I have no idea and no expectations of what great surprises and experiences tomorrow will bring but I'll be back with more attempts to capture and share this with you. I truly appreciate having you along for the ride albeit limited by my abilities to describe it all to you.
Wayne & Ruby the Wonderdog


text:
zest of one tangerine*
2 cups flour
1 cup sugar
1/2 cup butter, at room temperature
1/3 cup tangerine juice**
4 teaspoons baking powder
1/4 teaspoon salt
Preheat oven to 375. In a large bowl, cream together butter, zest and sugar. Add egg and juice, mix thoroughly. Add flour, baking powder and salt, mix until a thick dough forms and all of the ingredients are well incorporated. Drop tablespoonfuls on baking sheet and bake 10 minutes or until "set". The cookies will puff up quite a bit but they should no longer be shiny on the top and the bottoms should be lightly browned when you take them out of the oven. Cool on a wire rack, then eat!
*or tangelo
** no pulp!


text:
Compare Prices of TV Accessories from Leading Online Stores in Kenya. Best Prices for TV Accessories from Top Brands. Discover the Best TV Accessories price in Kenya. Conveniently shop for TV Accessories online and have it delivered to your doorsteps
How much does a TV Accessory cost in Kenya? Find Best prices and deals for TV Accessories in Kenya. Compare TV Accessories prices and pick one that meets your budget. Most online stores in Kenya ship to Lagos, Port Harcourt, Enugu, Abuja, Ibadan, Abeokuta, Osun, Uyo, Benin, Warri, Kaduna, Kano, Aba, Umuahia, Onitsha and other major cities, while the big online stores deliver nationwide.
See Prices Below:


text:
Max Kampelman, Voice for Soviet Jewry, Evolved But Never Changed
Max Kampelman, who died on January 25 at the age of 92, was lauded often as one of the great men of our times for his role as chief U.S. arms control negotiator in the Reagan administration. He won no less praise for his diplomatic role in enabling the emigration of hundreds of thousands of Jews from the Soviet Union.
Much less noted about this humble man was the profound evolution he underwent over the course of his life.
During World War II Kampelman, who served as a conscientious objector, volunteered for the Minnesota Starvation Experiment. As part of this University of Minnesota project, Kampelman allowed experiments to be performed on him that were vital to a better understanding of how people deal with and recover from starvation — an issue the Allies were preparing to confront on a mass basis as part of the war's immediate post-liberation phase.
But later, Kampelman rejected the pacifism of his youth in favor of support for a strong U.S. foreign policy to better promote human rights and secure peace in the world.
He grew up as the son of a butcher in the Bronx and went on to earn his law degree at night school at New York University — and then a master's and a doctorate in political science at the University of Minnesota. It was there that he met Hubert Humphrey, who was then the mayor of Minneapolis, and, like Kampelman, a progressive social democrat. Humphrey would become a senator and a presidential candidate. Max Kampelman was with him every step of the way.
When that period of his life was over, Kampelman became a skilled practitioner of law in Washington as a member of a firm that bore his name as a senior partner. But he was always more than a mere lawyer. Max could incorporate into his very being the ability to get along with nearly everyone while making his point with deft determination.
Government service called him back when President Jimmy Carter asked him to lead talks in Madrid aimed at drawing Soviet bloc nations into the Helsinki Accords, which were signed in 1975, and which enshrined among other rights the freedom to emigrate.
It was a reflection of the bipartisan nature of his advocacy that Carter's Republican successor, President Ronald Reagan, asked Max to stay on in his position. By 1983, Kampelman succeeded in extracting an agreement from the Soviet Union that was key in advancing the struggle to free Soviet Jewry.
Notwithstanding his stance as a military hawk, Kampelman remained at heart a staunch liberal when it came to domestic issues. He never wavered in his belief in the importance of government in protecting the poor, the elderly and, indeed, the middle class. It was this combination of views that led him to leave the Reagan administration in 1984 to advise Democratic presidential candidate Walter Mondale in 1984.
Nevertheless, after Reagan defeated Mondale, he invited Kampelman back into his administration, this time to negotiate nuclear arms reduction.
Amid all this, Max was also a mentor to me, and a role model. In actual fact, he changed the course of my professional life. When Jeane Kirkpatrick was looking for a personal counsel to represent her as she took on the arduous task of being the U.S. ambassador to the United Nations under Reagan, she turned to Max.
He, in turn, suggested that I was the person who could help navigate the shoals of the State Department and help her in her refusal to condemn as aggression Israel's bombing of an Iraqi nuclear reactor at Osirak in 1981. I accepted the position, and Max was always at my side to provide wise counsel.
Max was a man of conscience who understood that the ideal practice of law deals with the senses and not just the mind. He reacted to injustice not as a philosophical matter but as something that affected his core.
In recognition of his lifetime achievements, he has been awarded the highest civilian accolade that the United States government can provide. But it is his spirit — his ability to pierce the veil of indifference, to help the needy, to be true to his Jewish roots as well as to America's best ideals — that makes him a man who will be sorely missed by all who had the privilege of knowing him.
Allan Gerson is a Washington based international lawyer who served as counsel to U.N. ambassadors Jeane Kirpatrick and Vernon Walters, and as a deputy assistant attorney general in the U.S. Justice Department


text:
The Current website is an emerging and open knowledge base created and curated by its community of members. We gather resources, collections, reflections, inquiries, and stories about what it means to teach writing in our digital and interconnected world.
The Current has a Creative Commons Attribution-Sharealike 4.0 International license in order to support creative sharing and distribution of content. We are influenced by the idea of creating community through the establishment of a shared commons of work as well as through conversations with colleagues at Creative Commons and P2PU.
Our Terms of Use are meant to support the development of this knowledge base and work of this connected community. Please email us if you have any questions or concerns.
Our Terms of Use
Last updated July 1, 2018.
The National Writing Project ("NWP") offers these website services (the "Services") to you subject to the terms and conditions of use ("Terms") contained herein. By accessing, creating, or contributing to any of the community website sections at and under the subdomain https://thecurrent.educatorinnovator.org/ ("Site"), and in consideration for the Services we provide to you, you agree to abide by these Terms. NWP retains the right to revoke membership to the The Current community if the terms of use are not met. Please read the terms carefully before joining, posting to or creating any content.
1. Disclaimer Content on this Site, including profiles, resources, collections, discussions and feedback, express the research and opinions of the Service participants, and do not necessarily reflect the views of NWP. The editors of this Service do not typically edit participants' posts or other content and cannot confirm the accuracy or reliability of their submissions. Each participant is solely responsible for the information, analysis and/or recommendations contained in their submitted content.
2. Moderation Policy NWP is hosting these Services to help build the field of digital writing, teaching and learning. We intend for comments and content posted in this forum to be individually authored, collegial, thoughtful, and intellectually challenging or provocative—and also to meet basic standards of respect and accuracy in tone and content. Posted content and comments on this Site are subject to review and moderation by NWP to maintain the respect required for this forum to remain productive and respectful. Participants may also flag comments or content for administrative NWP review. Suggested guidelines are provided for both posting and responding to content within this site. We encourage the use of these guidelines in helping to establish shared practices and collegial dialogue within The Current. Voicing differences of opinion and providing countervailing information or analysis within the context of the site's intent are welcomed—however, hate speech and attacks of a personal nature will not be tolerated. NWP maintains the right to edit or remove content or comments posted at our discretion if said content or comments are unrelated to the general area of interest of the website or comment is unrelated to the post to which it is responding; if content or comments are advertising products, services, or websites rather than making points; or if contents or comments include racial, gender-based, or sexualized slurs or attacks, aggressive harassment or abuse of content authors or fellow site members, or threats of violence.
3. Rights in the Content You Submit Except where otherwise noted, all content on this Site is currently available under a Creative Commons Attribution-Sharealike 4.0 International. Unless you specify otherwise, any and all works of authorship copyrightable by you and posted by you to this Site ("Content") are submitted under these default terms. This site-wide license default established on December 3, 2013. Prior to these changes our default terms of use was a Creative Commons Attribution-NonCommercial-NoDerivs. Please note that by posting your Content on this Site, you are granting NWP a non-exclusive, royalty-free, perpetual, and worldwide license to use your Content in connection with the operation of the Services, including, without limitation, the license rights to copy, distribute, transmit, publicly display, publicly perform, reproduce, edit, translate and reformat your Content, and/or to incorporate it into a collective work. Attribution When publicly displaying, publicly performing, reproducing, or distributing copies of your Content, or Content as incorporated into a collective work, NWP will make best efforts to credit your authorship. You grant NWP permission to use your name for such attribution purposes. You, likewise, agree to represent yourself accurately. You acknowledge that misrepresentation may lead us, in our sole discretion, to cancel your use of the Services and delete any of your Content.
4. Conduct Posting You may not use the NWP name to endorse or promote any product, opinion, cause, or political candidate. Representation of your personal opinions as institutionally endorsed by NWP or any of its writing project sites is strictly prohibited. By posting any content, you warrant and represent that you either own or otherwise control all of the rights to that content, including, without limitation, all the rights necessary for you to provide, post, upload, input, or submit the content, or that your use of the content is a protected fair use. You agree that you will not knowingly and with intent to defraud provide material and misleading false information. You represent and warrant also that the content you supply does not violate these Terms and that you will indemnify and hold NWP harmless for any and all claims resulting from content you supply. When posting any content that is created by or features students under the age of 18, you also warrant and represent that you have all the necessary permissions required by your district or institution's acceptable use policy and that you are in compliance with protections afforded minors as per U.S. law. Furthermore, you warrant and represent that you have protected the privacy of minors in your content, including removing student names and other identifiers as per U. S. Law (i.e. CIPA/COPA) and your institutions acceptable use policy. You acknowledge that NWP does not pre-screen or regularly review posted content but that it shall have the right to remove in its sole discretion any content that it considers in violation of these Terms. Accessing You understand that all content posted to the Site is the sole responsibility of the individual who originally posted the content. You understand, also, that all opinions expressed by users of this site are expressed strictly in their individual capacities and not as representatives of NWP or their writing project sites. You agree that NWP or affiliated writing project sites will not be liable, under any circumstances and in any way, for any errors or omissions, loss or damage of any kind incurred as a result of use of any content posted on this site. You agree that you must evaluate and bear all risks associated with the use of any content, including any reliance on the accuracy, completeness, or usefulness of such content. Children Collecting personal information from children under the age of thirteen is prohibited. No Content should be directed toward such children without the express written permission of the NWP.
5. Disclaimer of Warranties and Limitation of Liability This site is provided on an "as is" and "as available" basis. NWP makes no representations or warranties of any kind, expressed or implied, as to the site's operation or the information, content or materials included on this site. To the full extent permissible by applicable law, NWP hereby disclaims all warranties, express or implied, including but not limited to implied warranties of merchantability and fitness for any particular purpose. NWP will not be liable for any damages of any kind arising from the use of or inability to use this site. You expressly agree that you use this site solely at your own risk.
6. Privacy Policy Please be sure to read the Site's Privacy Policy which is incorporated herein by reference.
7. Modification of These Terms of Use NWP reserves the right to change, at any time, at our sole discretion, the Terms under which these Services are offered. You are responsible for regularly reviewing these Terms. Your continued use of the Services constitutes your agreement to all such Terms.
8. Copyright Complaints NWP respects the intellectual property of others, and requires that our users do the same. If you believe that your work has been copied and is accessible on this site in a way that constitutes copyright infringement, or that your intellectual property rights have been otherwise violated, please contact NWP to report copyright infringements.
Privacy Policy
The National Writing Project (NWP) is committed to your right to privacy. To that end, NWP has adopted the following privacy policies with regard to the online collection of personal information.
Your Personal Information—What We Collect and Why
The Current requires your full name, email address, and a short bio to join. On a voluntary basis, members may provide further personal information as part of their individual profile. Because professional networking is an important benefit of being a The Current community member, NWP allows logged-in members to see other member's The Current profiles. The The Current profile shows the following information about each member according to the information provided by the member in his or her profile: interests, location via city and state, associated URLs, bio information, and recent activity in the site. Email addresses are not displayed at any time. (Please note, however, that usernames are displayed in relation to comments linked to discussion and feedback requests. First name and last name are displayed at all other times.) Email is visible to NWP staff administrators of The Current. NWP may request and collect additional personal data for participation in certain NWP activities. This additional information is requested solely for the purpose of official NWP business. If you contact NWP with a request, issue, or other communication, we may also ask you for additional personal information. NWP will use only the personal information you provide for official purposes, including but not limited to, official NWP communications, professional networking opportunities for The Current members, research analysis, and for government reporting or other legal requirements. NWP does not sell your personal information to third parties for commerce-related or marketing purposes. Personal information is also collected as part of spam protection. This information is handled by Mollom, and is treated according to the terms of Mollom's web service privacy policy.
Opting In/Out of Email The Current members can individually control how they receive information from the The Current website by editing notifications. Default settings have been established so that if you are the author of a resource, feedback request or comment, you will receive email from any responses. This can be changed as per your profile and account notification settings.
Online Postings to Discussions/Forum NWP discussions and forums provide our members with a valuable resource for sharing their experiences and knowledge. Any communications made through the NWP site, including postings to discussion groups and forums made on the Web or via email, are understood to be publicly available and will not be afforded any privacy or limitation of distribution.
External Links The The Current website contains links to other independently run websites outside the "nwp.org" domain. NWP is not responsible for the security and privacy practices or content of these external websites.
Cookies The Current uses cookies as a method of authentication. NWP does not sell information collected by cookies or use the information for commerce-related purposes.
Logs To help improve the user experience on our site, our system keeps two logs. The first log collects the time, IP address, page requested, and user agent string (which tells us what browser is being used). This information is used for system analysis to determine which browsers are popular with our members, which pages are most popular with members, how much time members spend on average on our site, and other general information that can be used for research purposes and system optimization. The second log records the time when a user logs into The Current, the IP address, and the The Current account number. Designated NWP staff use the login time for official purposes, including helping users with support requests and identifying abandoned accounts. NWP does not use logs for commerce-related purposes or sell information collected by logs. Some NWP applications may log additional user activity, which is solely intended for internal NWP use.
Your Agreement Use of this site constitutes acknowledgment and agreement of this privacy policy. We reserve the right to change all or part of this privacy policy at any time. Changes will be posted and your use of the site after such changes constitutes acceptance of the updated privacy policy.
Contact Information If you have any questions, please contact us at email@example.com.


text:
- City Fajr Shuruq Duhr Asr Magrib Isha
- Dubai 05:22 06:35 12:33 15:53 18:26 19:39
Lance Armstrong plans to admit to doping throughout his career in an interview with Oprah Winfrey next week, the American cyclist's first interview since being stripped of his seven Tour de France titles, USA Today reported on Saturday.
But Armstrong, 41, likely will not offer great detail about specific cases and events, the paper said, citing an unidentified source with knowledge of the situation.
The interview is scheduled to tape on Monday at Armstrong's home in Austin, Texas, and set to air on Thursday on the Oprah Winfrey Network.
Such an admission would mark a major reversal for the famed cyclist. Armstrong has always vehemently denied using performance-enhancing drugs and has never been proven to have tested positive.
But an October report from the U.S. anti-doping body USADA cited Armstrong's involvement in what it characterised as the "most sophisticated, professionalised and successful doping program that sport has ever seen," involving anabolic steroids, human growth hormone, blood transfusions and other doping.
Less than two weeks later, Armstrong's seven Tour de France victories were nullified and he was banned from cycling for life after the International Cycling Union ratified the USADA's sanctions against him.
The New York Times reported last week that Armstrong was considering an admission of using banned drugs with the hopes of persuading anti-doping officials to allow him to resume competition in athletic events that adhere to the World Anti-Doping Code.
Another motivation might be to keep the scandal from hurting Livestrong, the cancer-support charity he founded in 1997, USA Today said on Saturday. Armstrong, a survivor of testicular cancer, stepped down as a board member in November.
Armstrong's planned admission, however, carries the risk of getting him sued or held reliable by those who believe he defrauded them by lying about his use of drugs, the paper reported.
Follow Emirates 24|7 on Google News.


text:
The state Legislature was busy patting itself on the back last week for its full-fledged assault on property rights, voting to ban smoking in privately owned properties such as restaurants and bars. How ironic that it would do so while actively subsidizing a film industry that encourages smoking.
Rep. Lee Gonzales, D-Flint Township, told The Flint Journal after the smoking ban passed, "It's a darn good day for Michigan citizens as we're protecting public health." That's debatable. The longest running study in the nation (1960-1998) on the effects of second-hand or "environmental" smoke finds almost no relationship between environmental smoke and health issues in non-smoking spouses.
The study, published in the British Medical Journal, concluded that:
The results do not support a causal relation between environmental tobacco smoke and tobacco related mortality, although they do not rule out a small effect. The association between exposure to environmental tobacco smoke and coronary heart disease and lung cancer may be considerably weaker than generally believed.
What is not debatable is that legislators happily deprived private property owners of their right to use their property as they see fit. Many restaurants voluntarily banned smoking in their establishments long before the law was passed. Others have no qualms about allowing it. That means that birds of a smoking feather could flock together (or not) and non-smokers could do likewise. Voluntary association was the solution to this imaginary problem. If you don't like smoke, don't spend time with those who do. Pretty simple and peaceful, isn't it? Not for politicians.
What is neither simple nor peaceful is that Lansing's careerist political class is subsidizing the film industry to the tune of possibly $100 million or more each year. This in turn lowers the cost to produce films featuring smokers that make the habit look sexy. The Center for Tobacco Control Research and Education at the University of California-San Francisco in November published a study on film subsidies and smoking titled Taxpayer Subsidies for US Films with Tobacco Imagery.
The study looked at the amount of "recent public subsidies for youth-rated (G/PG/PG-13) films with tobacco imagery" and found that many states, including Michigan, spend more money on film subsidies than anti-tobacco programs:
States awarded an estimated $830 million in public subsidies to films with tobacco, including $500 million to youth-rated films with tobacco. For comparison, the states budgeted $719 million for all tobacco control in 2009. More than half of states subsidizing films (22/41), including New York and California, spend or earmark more money for commercial film subsidies than for anti-tobacco programs. An estimated 60 percent ($830 million/$1.4 billion) of state film subsidies go to smoking films.
The report notes that Michigan was to shell out $48 million in film subsidies (refunds) to movie makers based on their 2008 spending in the state, but Michigan spent only $5.1 million in 2009 on "tobacco prevention spending."
This quandary, however, may have solved itself in Michigan now that the workplace smoking ban is in place. After all, isn't a film set... a "workplace?"
Get insightful commentary and the most reliable research on Michigan issues sent straight to your inbox.
The Mackinac Center for Public Policy is a nonprofit research and educational institute that advances the principles of free markets and limited government. Through our research and education programs, we challenge government overreach and advocate for a free-market approach to public policy that frees people to realize their potential and dreams.
Please consider contributing to our work to advance a freer and more prosperous state.