Welcome to Chapter 3 of the "Implementing a language with LLVM" tutorial. This chapter shows you how to transform the Abstract Syntax Tree, built in Chapter 2, into LLVM IR. This will teach you a little bit about how LLVM does things, as well as demonstrate how easy it is to use. It's much more work to build a lexer and parser than it is to generate LLVM IR code. :)
Please note: the code in this chapter and later requires llvm-py 0.6 and LLVM 2.7. Earlier versions will most likely not work with it. Also note that you need to use a version of this tutorial that matches your llvm-py release: If you are using an official llvm-py release, use the version of the documentation on the llvm-py examples page.
In order to generate LLVM IR, we want some simple setup to get started. First we define code generation methods in each AST node class:
# Expression class for numeric literals like "1.0". class NumberExpressionNode(ExpressionNode): def __init__(self, value): self.value = value def CodeGen(self): ... # Expression class for referencing a variable, like "a". class VariableExpressionNode(ExpressionNode): def __init__(self, name): self.name = name def CodeGen(self): ... ...
The CodeGen method says to emit IR for that AST node along with all the things it depends on, and they all return an LLVM Value object. "Value" is the class used to represent a "Static Single Assignment (SSA) register" or "SSA value" in LLVM. The most distinct aspect of SSA values is that their value is computed as the related instruction executes, and it does not get a new value until (and if) the instruction re-executes. In other words, there is no way to "change" an SSA value. For more information, please read up on Static Single Assignment - the concepts are really quite natural once you grok them.
We will also need to define some global variables which we will be used during code generation:
# The LLVM module, which holds all the IR code. g_llvm_module = Module.new('my cool jit') # The LLVM instruction builder. Created whenever a new function is entered. g_llvm_builder = None # A dictionary that keeps track of which values are defined in the current scope # and what their LLVM representation is. g_named_values = {}
g_llvm_module is the LLVM construct that contains all of the functions and global variables in a chunk of code. In many ways, it is the top-level structure that the LLVM IR uses to contain code.
g_llvm_builder is a helper object that makes it easy to generate LLVM instructions. Instances of the llvm.core.Builder class keep track of the current place to insert instructions and have methods to create new instructions. Note that we do not initialize this variable; instead, it will be initialized whenever we start generating code for a function.
Finally, g_named_values is a dictionary that keeps track of which values are defined in the current scope and what their LLVM representation is. In other words, it is a symbol table for the code. In this form of Kaleidoscope, the only things that can be referenced are function parameters. As such, function parameters will be in this map when generating code for their function body.
With these basics in place, we can start talking about how to generate code for each expression. Note that this assumes that g_llvm_builder has been set up to generate code into something. For now, we'll assume that this has already been done, and we'll just use it to emit code.
Generating LLVM code for expression nodes is very straightforward: less than 35 lines of commented code for all four of our expression nodes. First we'll do numeric literals:
def CodeGen(self): return Constant.real(Type.double(), self.value)
In llvm-py, floating point numeric constants are represented with the llvm.core.ConstantFP class. To create one, we can use the static real() method in the llvm.core.Constant class. This code basically just creates and returns a ConstantFP. Note that in the LLVM IR constants are all uniqued together and shared. For this reason, we create the constant through a factory method instead of instantiating one directly.
def CodeGen(self): if self.name in g_named_values: return g_named_values[self.name] else: raise RuntimeError('Unknown variable name: ' + self.name)
References to variables are also quite simple using LLVM. In the simple version of Kaleidoscope, we assume that the variable has already been emitted somewhere and its value is available. In practice, the only values that can be in the g_named_values dictionary are function arguments. This code simply checks to see that the specified name is in the map (if not, an unknown variable is being referenced) and returns the value for it. In future chapters, we'll add support for loop induction variables in the symbol table, and for local variables.
def CodeGen(self): left = self.left.CodeGen() right = self.right.CodeGen() if self.operator == '+': return g_llvm_builder.fadd(left, right, 'addtmp') elif self.operator == '-': return g_llvm_builder.fsub(left, right, 'subtmp') elif self.operator == '*': return g_llvm_builder.fmul(left, right, 'multmp') elif self.operator == '<': result = g_llvm_builder.fcmp(FCMP_ULT, left, right, 'cmptmp') # Convert bool 0 or 1 to double 0.0 or 1.0. return g_llvm_builder.uitofp(result, Type.double(), 'booltmp') else: raise RuntimeError('Unknown binary operator.')
Binary operators start to get more interesting. The basic idea here is that we recursively emit code for the left-hand side of the expression, then the right-hand side, then we compute the result of the binary expression depending on which operator is being used.
In the example above, the LLVM builder class is starting to show its value. g_llvm_builder knows where to insert the newly created instruction, all you have to do is specify what instruction to create (e.g. with add), which operands to use (left and right here) and optionally provide a name for the generated instruction.
One nice thing about LLVM is that the name is just a hint. For instance, if the code above emits multiple "addtmp" variables, LLVM will automatically provide each one with an increasing, unique numeric suffix. Local value names for instructions are purely optional, but it makes it much easier to read the IR dumps.
LLVM instructions are constrained by strict rules: for example, the Left and Right operators of an add instruction must have the same type, and the result type of the add must match the operand types. Because all values in Kaleidoscope are doubles, this makes for very simple code for add, sub and mul.
On the other hand, LLVM specifies that the fcmp instruction always returns an 'i1' value (a one bit integer). The problem with this is that Kaleidoscope wants the value to be a 0.0 or 1.0 value. In order to get these semantics, we combine the fcmp instruction with a uitofp instruction. This instruction converts its input integer into a floating point value by treating the input as an unsigned value. In contrast, if we used the sitofp instruction, the Kaleidoscope '<' operator would return 0.0 and -1.0, depending on the input value.
def CodeGen(self): # Look up the name in the global module table. callee = g_llvm_module.get_function_named(self.callee) # Check for argument mismatch error. if len(callee.args) != len(self.args): raise RuntimeError('Incorrect number of arguments passed.') arg_values = [i.CodeGen() for i in self.args] return g_llvm_builder.call(callee, arg_values, 'calltmp')
Code generation for function calls is quite straightforward with LLVM. The code above initially does a function name lookup in the LLVM Module's symbol table. Recall that the LLVM Module is the container that holds all of the functions we are JIT'ing. By giving each function the same name as what the user specifies, we can use the LLVM symbol table to resolve function names for us.
Once we have the function to call, we codegen each argument that is to be passed in, and create an LLVM call instruction. Note that LLVM uses the native C calling conventions by default, allowing these calls to also call into standard library functions like "sin" and "cos", with no additional effort.
This wraps up our handling of the four basic expressions that we have so far in Kaleidoscope. Feel free to go in and add some more. For example, by browsing the LLVM language reference you'll find several other interesting instructions that are really easy to plug into our basic framework.
Code generation for prototypes and functions must handle a number of details, which make their code less beautiful than expression code generation, but allows us to illustrate some important points. First, let's talk about code generation for prototypes: they are used both for function bodies and external function declarations. The code starts with:
def CodeGen(self): # Make the function type, eg. double(double,double). funct_type = Type.function( Type.double(), [Type.double()] * len(self.args), False) function = Function.new(g_llvm_module, funct_type, self.name)
The call to Type.function creates the FunctionType that should be used for a given Prototype. Since all function arguments in Kaleidoscope are of type double, the first line creates a list of "N" LLVM double types. It then uses the Type.function method to create a function type that takes "N" doubles as arguments, returns one double as a result, and that is not vararg (the False parameter indicates this). Note that Types in LLVM are uniqued just like Constants are, so you don't instantiate them directly.
The final line above actually creates the function that the prototype will correspond to. This indicates the type and name to use, as well as which module to insert into. Note that by default, the function will have "external linkage", which means that the function may be defined outside the current module and/or that it is callable by functions outside the module. The name passed in is the name the user specified: since g_llvm_module is specified, this name is registered in g_llvm_module's symbol table, which is used by the function call code above.
# If the name conflicted, there was already something with the same name. # If it has a body, don't allow redefinition or reextern. if function.name != self.name: function.delete() function = g_llvm_module.get_function_named(self.name)
The Module symbol table works just like the Function symbol table when it comes to name conflicts: if a new function is created with a name was previously added to the symbol table, it will get implicitly renamed when added to the Module. The code above exploits this fact to determine if there was a previous definition of this function.
In Kaleidoscope, we choose to allow redefinitions of functions in two cases: first, we want to allow 'extern'ing a function more than once, as long as the prototypes for the externs match (since all arguments have the same type, we just have to check that the number of arguments match). Second, we want to allow 'extern'ing a function and then defining a body for it. This is useful when defining mutually recursive functions.
In order to implement this, the code above first checks to see if there is a collision on the name of the function. If so, it deletes the function we just created (by calling delete) and then calling get_function_named to get the existing function with the specified name.
# If the function already has a body, reject this. if not function.is_declaration: raise RuntimeError('Redefinition of function.') # If F took a different number of args, reject. if len(callee.args) != len(self.args): raise RuntimeError('Redeclaration of a function with different number ' 'of args.')
In order to verify the logic above, we first check to see if the pre-existing function is a forward declaration. Since we don't allow anything after a full definition of the function, the code rejects this case. If the previous reference to a function was an 'extern', we simply verify that the number of arguments for that definition and this one match up. If not, we emit an error.
# Set names for all arguments and add them to the variables symbol table. for arg, arg_name in zip(function.args, self.args): arg.name = arg_name # Add arguments to variable symbol table. g_named_values[arg_name] = arg return function
The last bit of code for prototypes loops over all of the arguments in the function, setting the name of the LLVM Argument objects to match, and registering the arguments in the g_named_values map for future use by the VariableExpressionNode. Note that we don't check for conflicting argument names here (e.g. "extern foo(a b a)"). Doing so would be very straight-forward with the mechanics we have already used above. Once this is all set up, it returns the Function object to the caller.
def CodeGen(self): # Clear scope. g_named_values.clear() # Create a function object. function = self.prototype.CodeGen()
Code generation for function definitions starts out simply enough: we just clear out the g_named_values dictionary to make sure that there isn't anything in it from the last function we compiled and codegen the prototype. Code generation of the prototype ensures that there is an LLVM Function object that is ready to go for us.
# Create a new basic block to start insertion into. block = function.append_basic_block('entry') global g_llvm_builder g_llvm_builder = Builder.new(block)
Now we get to the point where g_llvm_builder is set up. The first line creates a new basic block (named "entry"), which is inserted into the function. The second line declares that the global g_llvm_builder object is to be changed. The last line creates a new builder that is set up to insert new instructions into the basic block we just created. Basic blocks in LLVM are an important part of functions that define the Control Flow Graph. Since we don't have any control flow, our functions will only contain one block at this point. We'll fix this in Chapter 5 :).
# Finish off the function. try: return_value = self.body.CodeGen() g_llvm_builder.ret(return_value) # Validate the generated code, checking for consistency. function.verify()
Once the insertion point is set up, we call the CodeGen method for the root expression of the function. If no error happens, this emits code to compute the expression into the entry block and returns the value that was computed. Assuming no error, we then create an LLVM ret instruction, which completes the function. Once the function is built, we call verify, which is provided by LLVM. This function does a variety of consistency checks on the generated code, to determine if our compiler is doing everything right. Using this is important: it can catch a lot of bugs. Once the function is finished and validated, we return it.
except: function.delete() raise return function
The only piece left here is handling of the error case. For simplicity, we handle this by merely deleting the function we produced with the delete method. This allows the user to redefine a function that they incorrectly typed in before: if we didn't delete it, it would live in the symbol table, with a body, preventing future redefinition.
This code does have a bug, though. Since the PrototypeNode::CodeGen can return a previously defined forward declaration, our code can actually delete a forward declaration. There are a number of ways to fix this bug; see what you can come up with! Here is a testcase:
extern foo(a b) # ok, defines foo. def foo(a b) c # error, 'c' is invalid. def bar() foo(1, 2) # error, unknown function "foo"
For now, code generation to LLVM doesn't really get us much, except that we can look at the pretty IR calls. The sample code inserts calls to CodeGen into the Handle* functions, and then dumps out the LLVM IR. This gives a nice way to look at the LLVM IR for simple functions. For example:
ready> 4+5 Read a top-level expression: define double @0() { entry: ret double 9.000000e+00 }
Note how the parser turns the top-level expression into anonymous functions for us. This will be handy when we add JIT support in the next chapter. Also note that the code is very literally transcribed, no optimizations are being performed except simple constant folding done by the Builder. We will add optimizations explicitly in the next chapter.
ready> def foo(a b) a*a + 2*a*b + b*b Read a function definition: define double @foo(double %a, double %b) { entry: %multmp = fmul double %a, %a ; <double> [#uses=1] %multmp1 = fmul double 2.000000e+00, %a ; <double> [#uses=1] %multmp2 = fmul double %multmp1, %b ; <double> [#uses=1] %addtmp = fadd double %multmp, %multmp2 ; <double> [#uses=1] %multmp3 = fmul double %b, %b ; <double> [#uses=1] %addtmp4 = fadd double %addtmp, %multmp3 ; <double> [#uses=1] ret double %addtmp4 }
This shows some simple arithmetic. Notice the striking similarity to the LLVM builder calls that we use to create the instructions.
ready> def bar(a) foo(a, 4.0) + bar(31337) Read a function definition: define double @bar(double %a) { entry: %calltmp = call double @foo(double %a, double 4.000000e+00) ; <double> [#uses=1] %calltmp1 = call double @bar(double 3.133700e+04) ; <double> [#uses=1] %addtmp = fadd double %calltmp, %calltmp1 ; <double> [#uses=1] ret double %addtmp }
This shows some function calls. Note that this function will take a long time to execute if you call it.  Here you can see the big picture with all the functions referencing each other.
This wraps up the third chapter of the Kaleidoscope tutorial. Up next, we'll describe how to add JIT codegen and optimizer support to this so we can actually start running code!
Here is the complete code listing for our running example, enhanced with the LLVM code generator. Because this uses the llvm-py libraries, you need to download and install them.
#!/usr/bin/env python import re from llvm.core import Module, Constant, Type, Function, Builder, FCMP_ULT ################################################################################ ## Globals ################################################################################ # The LLVM module, which holds all the IR code. g_llvm_module = Module.new('my cool jit') # The LLVM instruction builder. Created whenever a new function is entered. g_llvm_builder = None # A dictionary that keeps track of which values are defined in the current scope # and what their LLVM representation is. g_named_values = {} ################################################################################ ## Lexer ################################################################################ # The lexer yields one of these types for each token. class EOFToken(object): pass class DefToken(object): pass class ExternToken(object): pass class IdentifierToken(object): def __init__(self, name): self.name = name class NumberToken(object): def __init__(self, value): self.value = value class CharacterToken(object): def __init__(self, char): self.char = char def __eq__(self, other): return isinstance(other, CharacterToken) and self.char == other.char def __ne__(self, other): return not self == other # Regular expressions that tokens and comments of our language. REGEX_NUMBER = re.compile('[0-9]+(?:\.[0-9]+)?') REGEX_IDENTIFIER = re.compile('[a-zA-Z][a-zA-Z0-9]*') REGEX_COMMENT = re.compile('#.*') def Tokenize(string): while string: # Skip whitespace. if string[0].isspace(): string = string[1:] continue # Run regexes. comment_match = REGEX_COMMENT.match(string) number_match = REGEX_NUMBER.match(string) identifier_match = REGEX_IDENTIFIER.match(string) # Check if any of the regexes matched and yield the appropriate result. if comment_match: comment = comment_match.group(0) string = string[len(comment):] elif number_match: number = number_match.group(0) yield NumberToken(float(number)) string = string[len(number):] elif identifier_match: identifier = identifier_match.group(0) # Check if we matched a keyword. if identifier == 'def': yield DefToken() elif identifier == 'extern': yield ExternToken() else: yield IdentifierToken(identifier) string = string[len(identifier):] else: # Yield the ASCII value of the unknown character. yield CharacterToken(string[0]) string = string[1:] yield EOFToken() ################################################################################ ## Abstract Syntax Tree (aka Parse Tree) ################################################################################ # Base class for all expression nodes. class ExpressionNode(object): pass # Expression class for numeric literals like "1.0". class NumberExpressionNode(ExpressionNode): def __init__(self, value): self.value = value def CodeGen(self): return Constant.real(Type.double(), self.value) # Expression class for referencing a variable, like "a". class VariableExpressionNode(ExpressionNode): def __init__(self, name): self.name = name def CodeGen(self): if self.name in g_named_values: return g_named_values[self.name] else: raise RuntimeError('Unknown variable name: ' + self.name) # Expression class for a binary operator. class BinaryOperatorExpressionNode(ExpressionNode): def __init__(self, operator, left, right): self.operator = operator self.left = left self.right = right def CodeGen(self): left = self.left.CodeGen() right = self.right.CodeGen() if self.operator == '+': return g_llvm_builder.fadd(left, right, 'addtmp') elif self.operator == '-': return g_llvm_builder.fsub(left, right, 'subtmp') elif self.operator == '*': return g_llvm_builder.fmul(left, right, 'multmp') elif self.operator == '<': result = g_llvm_builder.fcmp(FCMP_ULT, left, right, 'cmptmp') # Convert bool 0 or 1 to double 0.0 or 1.0. return g_llvm_builder.uitofp(result, Type.double(), 'booltmp') else: raise RuntimeError('Unknown binary operator.') # Expression class for function calls. class CallExpressionNode(ExpressionNode): def __init__(self, callee, args): self.callee = callee self.args = args def CodeGen(self): # Look up the name in the global module table. callee = g_llvm_module.get_function_named(self.callee) # Check for argument mismatch error. if len(callee.args) != len(self.args): raise RuntimeError('Incorrect number of arguments passed.') arg_values = [i.CodeGen() for i in self.args] return g_llvm_builder.call(callee, arg_values, 'calltmp') # This class represents the "prototype" for a function, which captures its name, # and its argument names (thus implicitly the number of arguments the function # takes). class PrototypeNode(object): def __init__(self, name, args): self.name = name self.args = args def CodeGen(self): # Make the function type, eg. double(double,double). funct_type = Type.function( Type.double(), [Type.double()] * len(self.args), False) function = Function.new(g_llvm_module, funct_type, self.name) # If the name conflicted, there was already something with the same name. # If it has a body, don't allow redefinition or reextern. if function.name != self.name: function.delete() function = g_llvm_module.get_function_named(self.name) # If the function already has a body, reject this. if not function.is_declaration: raise RuntimeError('Redefinition of function.') # If F took a different number of args, reject. if len(callee.args) != len(self.args): raise RuntimeError('Redeclaration of a function with different number ' 'of args.') # Set names for all arguments and add them to the variables symbol table. for arg, arg_name in zip(function.args, self.args): arg.name = arg_name # Add arguments to variable symbol table. g_named_values[arg_name] = arg return function # This class represents a function definition itself. class FunctionNode(object): def __init__(self, prototype, body): self.prototype = prototype self.body = body def CodeGen(self): # Clear scope. g_named_values.clear() # Create a function object. function = self.prototype.CodeGen() # Create a new basic block to start insertion into. block = function.append_basic_block('entry') global g_llvm_builder g_llvm_builder = Builder.new(block) # Finish off the function. try: return_value = self.body.CodeGen() g_llvm_builder.ret(return_value) # Validate the generated code, checking for consistency. function.verify() except: function.delete() raise return function ################################################################################ ## Parser ################################################################################ class Parser(object): def __init__(self, tokens, binop_precedence): self.tokens = tokens self.binop_precedence = binop_precedence self.Next() # Provide a simple token buffer. Parser.current is the current token the # parser is looking at. Parser.Next() reads another token from the lexer and # updates Parser.current with its results. def Next(self): self.current = self.tokens.next() # Gets the precedence of the current token, or -1 if the token is not a binary # operator. def GetCurrentTokenPrecedence(self): if isinstance(self.current, CharacterToken): return self.binop_precedence.get(self.current.char, -1) else: return -1 # identifierexpr ::= identifier | identifier '(' expression* ')' def ParseIdentifierExpr(self): identifier_name = self.current.name self.Next() # eat identifier. if self.current != CharacterToken('('): # Simple variable reference. return VariableExpressionNode(identifier_name) # Call. self.Next() # eat '('. args = [] if self.current != CharacterToken(')'): while True: args.append(self.ParseExpression()) if self.current == CharacterToken(')'): break elif self.current != CharacterToken(','): raise RuntimeError('Expected ")" or "," in argument list.') self.Next() self.Next() # eat ')'. return CallExpressionNode(identifier_name, args) # numberexpr ::= number def ParseNumberExpr(self): result = NumberExpressionNode(self.current.value) self.Next() # consume the number. return result # parenexpr ::= '(' expression ')' def ParseParenExpr(self): self.Next() # eat '('. contents = self.ParseExpression() if self.current != CharacterToken(')'): raise RuntimeError('Expected ")".') self.Next() # eat ')'. return contents # primary ::= identifierexpr | numberexpr | parenexpr def ParsePrimary(self): if isinstance(self.current, IdentifierToken): return self.ParseIdentifierExpr() elif isinstance(self.current, NumberToken): return self.ParseNumberExpr() elif self.current == CharacterToken('('): return self.ParseParenExpr() else: raise RuntimeError('Unknown token when expecting an expression.') # binoprhs ::= (operator primary)* def ParseBinOpRHS(self, left, left_precedence): # If this is a binary operator, find its precedence. while True: precedence = self.GetCurrentTokenPrecedence() # If this is a binary operator that binds at least as tightly as the # current one, consume it; otherwise we are done. if precedence < left_precedence: return left binary_operator = self.current.char self.Next() # eat the operator. # Parse the primary expression after the binary operator. right = self.ParsePrimary() # If binary_operator binds less tightly with right than the operator after # right, let the pending operator take right as its left. next_precedence = self.GetCurrentTokenPrecedence() if precedence < next_precedence: right = self.ParseBinOpRHS(right, precedence + 1) # Merge left/right. left = BinaryOperatorExpressionNode(binary_operator, left, right) # expression ::= primary binoprhs def ParseExpression(self): left = self.ParsePrimary() return self.ParseBinOpRHS(left, 0) # prototype ::= id '(' id* ')' def ParsePrototype(self): if not isinstance(self.current, IdentifierToken): raise RuntimeError('Expected function name in prototype.') function_name = self.current.name self.Next() # eat function name. if self.current != CharacterToken('('): raise RuntimeError('Expected "(" in prototype.') self.Next() # eat '('. arg_names = [] while isinstance(self.current, IdentifierToken): arg_names.append(self.current.name) self.Next() if self.current != CharacterToken(')'): raise RuntimeError('Expected ")" in prototype.') # Success. self.Next() # eat ')'. return PrototypeNode(function_name, arg_names) # definition ::= 'def' prototype expression def ParseDefinition(self): self.Next() # eat def. proto = self.ParsePrototype() body = self.ParseExpression() return FunctionNode(proto, body) # toplevelexpr ::= expression def ParseTopLevelExpr(self): proto = PrototypeNode('', []) return FunctionNode(proto, self.ParseExpression()) # external ::= 'extern' prototype def ParseExtern(self): self.Next() # eat extern. return self.ParsePrototype() # Top-Level parsing def HandleDefinition(self): self.Handle(self.ParseDefinition, 'Read a function definition:') def HandleExtern(self): self.Handle(self.ParseExtern, 'Read an extern:') def HandleTopLevelExpression(self): self.Handle(self.ParseTopLevelExpr, 'Read a top-level expression:') def Handle(self, function, message): try: print message, function().CodeGen() except Exception, e: print 'Error:', e try: self.Next() # Skip for error recovery. except: pass ################################################################################ ## Main driver code. ################################################################################ def main(): # Install standard binary operators. # 1 is lowest possible precedence. 40 is the highest. operator_precedence = { '<': 10, '+': 20, '-': 20, '*': 40 } # Run the main "interpreter loop". while True: print 'ready>', try: raw = raw_input() except KeyboardInterrupt: break parser = Parser(Tokenize(raw), operator_precedence) while True: # top ::= definition | external | expression | EOF if isinstance(parser.current, EOFToken): break if isinstance(parser.current, DefToken): parser.HandleDefinition() elif isinstance(parser.current, ExternToken): parser.HandleExtern() else: parser.HandleTopLevelExpression() # Print out all of the generated code. print '\n', g_llvm_module if __name__ == '__main__': main()


WhatsApp adds shopping catalog feature, courting e-commerce
by ReutersSAN FRANCISCO: Facebook on Thursday launched a catalog feature for its WhatsApp messaging app, it said in a blog post, building out the service’s e-commerce tools as it moves slowly toward monetising the app it bought in 2014 for $19 billion.
Facebook has been trying to boost revenue from higher-growth units like Instagram and Whatsapp, which has 1.5 billion users. The company’s flagship News Feed product continues to draw big ad dollars but is struggling to generate new users.
The move comes after Facebook added a shopping feature to Instagram in March that lets users click a “checkout” option on items tagged for sale and pay for them directly within the app.
The new WhatsApp tool stops short of that, as transactions still occur elsewhere. But small businesses, the main users of the free WhatsApp Business app, can now display a “mobile storefront” showcasing their wares with images and prices.
“We’re opening commerce as a new chapter,” Amrit Pal, a product manager at WhatsApp, told Reuters.
“We hear from businesses every day that WhatsApp is where they meet their customers, rather than sending them to a website.”
Chief Executive Officer Mark Zuckerberg has announced plans to shift the company’s focus to private chats, adding bots and augmented reality tools in recent years to encourage businesses to communicate with consumers on its messaging services.
Facebook said last year that it would start charging businesses for sending marketing and customer service messages on WhatsApp at a fixed rate for confirmed delivery, ranging from 0.5 cents to 9 cents per message depending on the country.
More than 100 businesses are now using that paid product, according to a WhatsApp spokesman, while around 5 million use the free WhatsApp Business service. Facebook has not disclosed revenue from it is business messaging efforts.
WhatsApp’s catalog feature is available for users in Brazil, Germany, India, Indonesia, Mexico, Britain, and the United States and will be rolled out around the world in the next few weeks, said the spokesman.


(that we call 'checks' BTW, to avoid conflicts with all your favorite test runners)
Check.That()
is all you've got to remember! before you get carried away by the super-duper-happy-DOT experience of NFluent (i.e. the IntelliSense experience)
var integers = new int[] { 1, 2, 3, 4, 5, 666 }; Check.That(integers).Contains(3, 5, 666); integers = new int[] { 1, 2, 3 }; Check.That(integers).IsOnlyMadeOf(3, 2, 1); var guitarHeroes = new[] { "Hendrix", "Paco de Lucia", "Django Reinhardt", "Baden Powell" }; Check.That(guitarHeroes).ContainsExactly("Hendrix", "Paco de Lucia", "Django Reinhardt", "Baden Powell"); var camus = new Person() { Name = "Camus" }; var sartre = new Person() { Name = "Sartre" }; Check.That(camus).IsNotEqualTo(sartre).And.IsInstanceOf<Person>(); var heroes = "Batman and Robin"; Check.That(heroes).Not.Contains("Joker").And.StartsWith("Bat").And.Contains("Robin"); int? one = 1; Check.That(one).HasAValue().Which.IsPositive().And.IsEqualTo(1); const Nationality FrenchNationality = Nationality.French; Check.ThatEnum(FrenchNationality).IsNotEqualTo(Nationality.Korean); string motivationalSaying = "Failure is mother of success."; Check.That(motivationalSaying).IsNotInstanceOf<int>();With NFluent, you can also write checks like this:
var persons = new List<Person> { new Person { Name = "Thomas", Age = 38 }, new Person { Name = "Achille", Age = 10, Nationality = Nationality.French }, new Person { Name = "Anton", Age = 7, Nationality = Nationality.French }, new Person { Name = "Arjun", Age = 7, Nationality = Nationality.Indian } }; Check.That(persons.Extracting("Name")).ContainsExactly("Thomas", "Achille", "Anton", "Arjun"); Check.That(persons.Extracting("Age")).ContainsExactly(38, 10, 7, 7); Check.That(persons.Extracting("Nationality")).ContainsExactly(Nationality.Unknown, Nationality.French, Nationality.French, Nationality.Indian); // more fluent than the following classical NUnit way, isn't it? // CollectionAssert.AreEquivalent(persons.Extracting("Age"), new[] { 38, 10, 7, 7 }); // it's maybe even more fluent than the java versions // FEST fluent assert v 2.x: // assertThat(extractProperty("name" , String.class).from(inn.getItems())).containsExactly("+5 Dexterity Vest", "Aged Brie", "Elixir of the Mongoose", "Sulfuras, Hand of Ragnaros", "Backstage passes to a TAFKAL80ETC concert", "Conjured Mana Cake"); // FEST fluent assert v 1.x: // assertThat(inn.getItems()).onProperty("name").containsExactly("+5 Dexterity Vest", "Aged Brie", "Elixir of the Mongoose", "Sulfuras, Hand of Ragnaros", "Backstage passes to a TAFKAL80ETC concert", "Conjured Mana Cake");Or like this:
// Works also with lambda for exception checking Check.ThatCode(() => { throw new InvalidOperationException(); }).Throws<InvalidOperationException>(); // or execution duration checking Check.ThatCode(() => Thread.Sleep(30)).LastsLessThan(60, TimeUnit.Milliseconds);
With truly-helpful error messages provided, NFluent spares you a few sessions with the debugger in your day to day work
Another booster for your productivity, and to reduce your TDD feedback loop ;-)
Indeed, NFluent is less error-prone for your day to day work.
Here, the distinction between the expected value and the one to be checked is natively enforced by the NFluent syntax. Thus, no question to ask ourselves when we write our assertions. And no question to ask ourselves when consulting the error messages on our Software Factory dashboard.
Very close to plain English, the NFluent syntax makes your tests easier to read even for non-developers people (QA, BA)
You wanna try? Follow the white rabbit here, or read the nice article published by Rui on CodeDistillers' blog.
. . .
Indeed, NFluent is simply an awesome assertion library, and ... she's not exclusive ;-)
There were attempts made previously by other open source projects, but even the most serious alternative did not suit our needs.
Indeed:
.Should()
.... why don't they choose Must instead?!?). And thus, you'd rather rely on a stronger semantic for your checks (i.e. NFluent's Check.That
).var myArray = new[] { 1, 2, 3 }; myArray.Should().Contain(item => item > 3, "at least {0} item should be larger than 3", 1);
Check.That(myArray).IsGreaterThan(3);
new[] {...}
as a method argument like does another famous "fluent" library?
myArray.Should().Have.SameSequenceAs(new[] { 1, 2, 3 });
Check.That(myArray).ContainsExactly(1,2,3);


{% load static %} {% static "images" as baseUrl %}
If you don't have account press SignUp to create account
{{message}}


Colin Leath
Summer 2009
|
6556 Pardall Rd #125
Goleta, CA 93117 |
805 403 7368<EMAIL_ADDRESS>|
Highlights
Experience
|
Spring 2004-Summer 2008 |
Challenge Course Facilitator, Lead Facilitator, Leadership Camp Lead
Ray and Joan Kroc Corps Community Center (& four other companies) San Diego, California Designed team development programs to meet client goals. Supervised co-facilitators and trainees. Inspected course. Designed and led two sessions of a week-long leadership skills program for counselors-in-training. |
|||||||
|
|
|
|||||||
|
Fall 2001-Spring 2003 |
Research Support Specialist Department of Vision Sciences, SUNY State College of Optometry New York, New York Wrote software to create and present visual displays and to collect and analyze data using 3ds max, MAXScript, R language, and Python with Pygame and OpenGLContext modules. Supported all parts of the research process, including experimental design, recruiting and running study participants, apparatus construction, and data analysis and presentation. |
|||||||
|
|
|
|||||||
|
Fall 1999-Spring 2001 |
VB Programmer (3rd), Install Developer (2nd), QA Analyst (1st) Greentree Systems Incorporated Pacific Grove, California GSI is a vendor of applicant tracking and resume scanning software. + Configured Windows NT and 9x systems to troubleshoot bugs and test software. Wrote release notes and managed bug report database. Worked with developers to verify important fixes were effected without causing new issues. Worked with customers and customer service to reproduce bugs and to support beta product. Maintained product installation scripts.+ Began working primarily on install development in spring 2000. + Designed and coded software which fully automated the complex, error-prone, hour-long iGreentree Server manual installation procedure, reducing novice installation times to less than 15 minutes. + Promoted to Visual Basic Programmer in February 2001. + Maintained, enhanced, and documented the Resume Analyzer component of the Greentree Employment System. Continued to maintain installs. |
|||||||
|
|
|
|||||||
|
Summer 1999-Fall 1999 |
Librarian Acquisition Library, Systems Management Dept., Naval Postgraduate School Monterey, California Implemented a Microsoft Access-based cataloging system, enabling students to search selected information about 1,200 of the library's items. Previously only paper indices of library documents were available. |
|||||||
|
|
|
|||||||
|
Spring 1997-Spring 1998 |
Research Assistant University of Washington, School of Nursing, Reconnecting Youth project Seattle, Washington Analyzed data using SPSS: constructed scales, tested their validity, and ran regressions, ANOVAs, t-tests, and other statistics. Summarized findings. |
|||||||
|
|
|
|||||||
|
Summer 1995-Fall 1996 |
Computer Lab Assistant University of Washington, Computing & Communications Seattle, Washington Helped students, staff, and faculty use campus computer systems via phone, via email, and in person. Created and troubleshot computer accounts. |
Other Experience
|
Summer 2008 |
Eight-week Sierra walk: Kernville to Tuolumne Meadows and back |
|
Summer 2008 |
Sewed clothes and equipment: quilt, tarp, hat, scarf, pack |
|
Fall 2006-Spring 2008 |
Gardener, participant, and volunteer, San Diego Food Not Lawns |
|
Summer 2007 |
Kitchen assistant at Quail Springs during two-week permaculture course |
|
Summer 2007 |
Vipassana meditation course, ten days |
|
Summer 2004 |
Staff, Hostel Obispo |
|
Spring 2003-Fall 2003 |
Bicycle tour: New York City to San Diego |
|
Fall 2002-Spring 2003 |
Volunteer chorister, Saint Bartholomew's Church, New York City |
|
Summer 2000-Spring 2002 |
Modern and ballet dance training, Monterey area and New York City |
|
Summer 2001 |
Counselor at English camps in Italy |
|
Summer 1999-Spring 2001 |
Monterey Hostel Society volunteer |
|
Fall 1998-Fall 1999 |
Temporary employee in Washington, DC, Austin, TX, and Monterey, CA |
|
Fall 1997-Summer 1998 |
Designed and ran 8-week research study, "The effect of participation in the Meaning in Life Forum on participants' experiences of meaning in life" |
|
Fall 1994-Spring 1995 |
Computer instructor for 4th and 5th graders |
|
Summer 1992-Summer 1994 |
Sailing and windsurfing instructor |
|
Spring 1991 |
Eagle Scout service project |
Publications
Leath, Colin, ed. SD/TJ Design, Plant, Harvest: nourishing our shared space, caring for the commons. Fall 2007-Summer 2008. <http://sdtjdph.blogspot.com/>
A collaborative blog designed to demonstrate read/write web technologies to San Diego- and Tijuana-area activists.
Leath, Colin, ed. The carfree universe project: Strengthening communities of the carfree. Spring 2003‑Fall 2007. <http://carfreeuniverse.org/>
A multi-user content management system which enabled tagging and sorting of content by topic, location, and content type.
Sedgwick, Harold, Barbara Gillam, and Colin Leath. Modeling perceived direction of slant in the presence of surface texture anisotropy [Abstract]. Journal of Vision, 3(9):496, 496a. Fall 2003. <http://journalofvision.org/3/9/496/>
Education
San Diego State University. Spring 2004-Fall 2006. English- and Spanish-language literature and TESOL.
University of Washington. Bachelor of Science with departmental honors in Psychology, Summer 1999. Calculus, physics, chemistry, and biology coursework.
Thomas Jefferson High School for Science and Technology. Diploma, Spring 1994. Computer science, computer architecture, digital electronics, and computer-aided design coursework.
References
|
Andrea Sanford Day Camps Manager Ray and Joan Kroc Corps Community Center |
H. A. Sedgwick, PhD Associate Professor State University of New York State College of Optometry |
Mike Strasser Director of Software Development Greentree Systems, Inc.
|


--- layout: default title: Head - Productions - Fail Better Productions menu-item: productions submenu-item: head styles: - /css/colours.css - ../production.css # - ./styles.css styles-ie6: ../production-ie6.css ---
This brand new play by a talented new writer received its world premiere at the 2004 Edinburgh Fringe Festival. Set on a South London estate, Head follows the story of two young lovers, Head and Urchin. At times ferocious, at times delicate, this is a stunning piece about destructive love and the terrors of adolescence. Zoë Simon's previous plays include After Dark and The Daughter of Frankenstein. She collaborated with the company in 2003 on their devised piece Echo and Narcissus and was Fail Better's Associate Artist for their 2004 season.
Playwright Zoë Simon says: "I began with a young woman who had an unstoppable desire to express herself. That was in June 2003. A year later, I had the sixth and final draft of a full-length play about a doomed relationship in a deeply violent, savagely beautiful world. Head examines the most complex and extreme human emotions, but also the simple excitement of being in love for the first time. It confronts the difficulties involved in growing up and the incompatibility of individuality and party politics. On a more abstract level it looks at the objective versus the subjective. Neither I, nor Jonathan Heron, who worked with me as a Dramaturg on Head, had any idea that we would end up where we did. However, we are both fearless when it comes to theatre, so we were quite happy to abandon the roller coaster ride in favour of hurling ourselves off the precipice."
"A devastating, abstract piece of cruelty ... relevant and powerful."
**** Three Weeks;
"Wonderfully poetic script ... powerfully acted ... impressive set"
The Stage;
"A dramatic tour de force"
Edinburgh Evening News.
To read reviews of this production, click here


<canvas>
<canvas>
Element can be used to draw graphics via scripting (usually JavaScript). For example, it can be used to draw graphs, make photo compositions or even perform animations. You may (and should) provide alternate content inside the <canvas>
block. That content will be rendered both on older browsers that don't support canvas and in browsers with JavaScript disabled.<noscript>
<noscript>
Element defines a section of html to be inserted if a script type on the page is unsupported or if scripting is currently turned off in the browser.<script>
<script>
element (or HTML Script Element ) is used to embed or reference an executable script within an HTML or XHTML document.


For function "recursiveMin", write
the missing part of the recursive call. This function
should return the minimum element in an array of
integers. You should assume that "recursiveMin" is
initially called with "startIndex" = 0.
Each time the recursive call is executed, startindex should be incremented so that the recursive case action passes through all the values in the array.


Murder in America is deeply local. Homicides in the U.S. rose about 9% last year, according to the Federal Bureau of Investigation, and more than one-third of the increase was concentrated in neighborhoods where just one-third of Chicago residents live. Meanwhile, improvements in areas where 30% of Los Angeles residents live accounted for one quarter of the 13% drop in U.S. murders between 2002 and 2014.


A perfect blend of versatility and style, jeans let you flaunt a variety of looks. From sauve washed denims to rugged distressed ones, flattering skinny fits to fabulous tapered ones, We have brought you power house denim brands just in a click.


Google Summer of Code, 2016
Abdul Fatir Ansari with Computational Biology @ University of Nebraska-Lincoln
Introduction
The aim of this project is to use the camera and processing power of modern day cell phones to develop an intuitive and user-friendly application for the detection and concentration estimation of various bio-markers in blood sample images. It is later planned to be used as a screening test for cancer. The application will allow the user to take images of the blood samples in a set format. The image will then be segmented to detect the regions of interest. After noise removal, the intensity of each individual blob will be calculated. A linear curve will be fit through the intensity and known concentration data and the concentrations of the unknown samples will be estimated from the standard curve which will quantify the various molecules present in the sample.
Demo
A video showing entire usage flow of the final Android Application with both demo mode on and off is exhibited below.
The algorithm developed for detection is fairly robust. We tested it against images of very bad quality, taken in bad lighting and it performed well. Here is a video showing the robustness of detection using our algorithm.
Sources
This project has been created from scratch and the sources for Android Studio can be found in this repository. A list of commits can be found here.
How to Build
Clone the repository or download it as a zip file and extract it.
Open Android Studio and import the directory as an existing Android project.
Usage
Android Phone
On your Android phone go to Settings > Security and Allow installation of apps from unknown sources.
Download and Install ConcAnalyzerv1.1.apk from here on your phone.
On first run, you'll be prompted whether to keep demo mode on.
Choose Load Image option and open image of the card with blood sample from your phone's Gallery (local storage). Images of this dataset can be used. To be able to use the Take Picture option, you need to have a physical test card. You can get a printout of one of these images and use it instead for testing. When taking a picture, keep the background distraction-less (white preferably).
Make sure that the image is loaded in portrait orientation. Rotate if necessary. It should be loaded like this and not like this. Check Known Issues.
Tap on Analyze. If the analysis is successful, the detected regions of interest will be highlighted using green color. If the demo mode is on, the detected regions will be highlighted in red. A red highlight indicates that the details for that blob have been updated.
If the demo mode is off, tap on each detected blob to enter its details. Once the details are entered for a blob, its highlight will turn red. Concentrations of Standard and Quality Control samples are given below.
S1, S2, S3, S4, S5: Standard Samples, QC: Quality Control Sample, UK: Unknown Sample
Sample Name
Concentration (ng/mL)
S1
100
S2
150
S3
250
S4
300
S5
350
QC
200
Tap on Results and the estimated concentration of the unknown sample will be shown along with the standard curve. A message will be shown if the error in the calculation of the concentration of the quality control sample exceeds 20%.
Note: The application has been tested on Android versions 5.0, 5.1, and 6.0 on Samsung, Moto and Xiaomi phones. The application may or may not work properly on pre-Lollipop Android devices.
Details of the Algorithm Used
Let \(I_{raw}\) be the original image of the test card in portrait scaled to a width of 600 while maintaining the aspect ratio.
\(I_{raw}\) : The Raw Image
Convert \(I_{raw}\) to grayscale to get \(I_{gray}\).
\(I_{gray}\) : The Raw Image in Grayscale
Apply 5x5 Gaussian Blur to \(I_{gray}\) to get \(I_{gb}\).
\(I_{gb}\) : Gaussian Blurred \(I_{gray}\)
Apply Adaptive Threshold to \(I_{gb}\) with a block-size of 85, C-value of 2 and method MEAN_C to get a binary image \(I_{th}\).
\(I_{th}\) : \(I_{gb}\) after Adaptive Threshold
Apply morphological closing to \(I_{th}\) using a rectangular structuring element of size 15x15 to get \(I_{mo}\).
\(I_{mo}\) : \(I_{th}\) after Morphological Closing
Find the contours in \(I_{mo}\) and filter the found contours based on following criteria.
Area bounded by the contour lies between 1000 and 16000.
Aspect ratio of the rectangle bounding the contour lies between 1 and 1.5.
Green and Blue boxes represent contours satisfying and not satisfying the set criteria respectively
Find the co-ordinates of center of all rectangles bounding these filtered contours.
Check the number of rectangular regions which lie within \(\pm15\) pixels in \(Y\) direction. If exactly 6 such regions are found, the algorithm proceeds. These six regions represent the standard and quality control samples.
Find another blob whose center is at least 20 pixels away from the centers of the standard samples in the \(Y\) direction and lies approximately in the horizontal center of the 6 blobs.
The Final Detections. Green: Standard and Quality Control samples, Blue: Unknown sample.
For each blob \(B\) of the 7 blobs.
Clip the rectangular portion bounding \(B\) from \(I_{gray}\) to get \(R_{gray}\).
Apply Otsu's binarization to \(R_{gray}\) to get \(R_{th}\).
Iterate over every pixel of \(R_{gray}\) and sum the intensities of all pixels where \(R_{th}\) is 0. Let the sum be \(S\).
Calculate average \(A = S/N\) where is \(N\) is the number of pixels in \(R_{th}\) with value 0.
Using the average intensity values and known concentration values of the five standard samples to train a linear regression model to get slope and intercept of the curve.
The Linear Regression
Calculate the concentration of the quality control and unknown samples using the slope and intercept values.
Check if the calculated concentration value of quality control sample lies within 20% error bound.
Known Issues
In some Samsung and Mi phones, at times the image taken from the camera is rotated after capture. For the application to function, the test card should be loaded in portrait orientation like this, and not in landscape. Therefore, when using the camera feature, the picture should be taken such that it loads as a portrait image.
Acknowledgment
I'm indebted to Dr. Tomas Helikar for giving me the opportunity of working on this amazing project. I would also like to thank Philipp Jahoda, whose library, MPAndroidChart, has been used in this project. It has been released under Apache License 2.0.


This spell channels vitality into plants within a specific area. There are two possible uses for the spell, granting either immediate or long-term benefits.
If you cast this spell using 1 action, choose a point within range. All normal plants in a 100-foot radius centered on that point become thick and overgrown. A creature moving through the area must spend 4 feet of movement for every 1 foot it moves.
You can exclude one or more areas of any size within the spell's area from being affected.
If you cast this spell over 8 hours, you enrich the land. All plants in a half-mile radius centered on a point within range become enriched for 1 year. The plants yield twice the normal amount of food when harvested.


How to create a virtual machine using Terraform on Azure Stack
This document explains how to create a VM using the azurestack Terraform provider with Service Principal Name authentication.
Prerequisites
Prerequisites from a Windows-based external client.
Terraform executable
An active Azure Subscription (required to create SPN if you want to use the same SPN for both Azure and Azure Stack)
Service Principal Name
Official Documentation
How to use Terraform with Azure Stack
Authentication
In order to authenticate with Terraform you will need to have a valid Service Principal Name (SPN) - how to create one is described in Prerequisites.
Note
You only need your Service Principal Name (SPN) to be assigned to your Azure Stack subscription, despite what official Terraform documentation says.
The process of authentication can be handled in one of two ways, either as Environment Variables or in the Provider Block.
Environment Variables Option - you can create your terraform plan by putting only the plan itself into example.tf
and then keep variables.tf
separate. You have to declare the actual values in the terraform.tfvars
file. This is the file that you will need to populate with your actual credential details.
Note
You can also put the content of variables.tf
in the example.tf
at the top of the file.
Provider Block Option - you can create your terraform plan by putting everything in one example.tf
file, which then contains your Provider settings explicitly in said plan.
Official Variables Guide
Example of Environment Variables
variables.tf
variable "arm_endpoint" {} variable "subscription_id" {} variable "client_id" {} variable "client_secret" {} variable "tenant_id" {}
example.tf
provider "azurestack" { arm_endpoint = "${var.arm_endpoint}" subscription_id = "${var.subscription_id}" client_id = "${var.client_id}" client_secret = "${var.client_secret}" tenant_id = "${var.tenant_id}" }
terraform.tfvars
# Configure the Azure Stack Provider arm_endpoint = "https://management.{region}.{domain}" subscription_id = "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx" client_id = "{applicationId}@{tenantDomain}" client_secret = "{applicationSecret}" tenant_id = "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx"
Example of Provider Block
example.tf
# Configure the Azure Stack Provider provider "azurestack" { arm_endpoint = "https://management.{region}.{domain}" subscription_id = "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx" client_id = "{applicationId}@{tenantDomain}" client_secret = "{applicationPassword}" tenant_id = "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx" }
Argument Reference
arm_endpoint
- The Azure Resource Manager API Endpoint for your Azure Stack instance. This will behttps://management.{region}.{domain}
.
Note
For UKCloud Region it is https://management.frn00006.azure.ukcloud.com
.
subscription_id
- The ID of your Azure Stack Subscription.client_id
- The Application GUID that you configured your Service Principal Name (SPN) to use.client_secret
- The Application password that you configured your Service Principal Name (SPN) to use.tenant_id
- The tenant ID of your Azure Active Directory tenant domain. It can either be the actual GUID or your Azure Active Directory tenant domain name.
Creating a VM
The examples that follow show how to create a VM using Terraform. The code changes depending on whether you are creating a VM with an unmanaged disk or a managed disk. Select the the type of disk you want to use to update the examples below with the appropriate code.
Create a VM with Public IP template - using Environment Variables option
Important
This is only the example.tf
file. You will still need the variables.tf
and terraform.tfvars
files in your folder.
provider "azurestack" {
arm_endpoint = "${var.arm_endpoint}"
subscription_id = "${var.subscription_id}"
client_id = "${var.client_id}"
client_secret = "${var.client_secret}"
tenant_id = "${var.tenant_id}"
}
# Create a resource group
resource "azurestack_resource_group" "test" {
name = "rg01"
location = "frn00006"
}
resource "azurestack_public_ip" "test" {
name = "acceptanceTestPublicIp1"
location = "${azurestack_resource_group.test.location}"
resource_group_name = "${azurestack_resource_group.test.name}"
public_ip_address_allocation = "static"
tags {
environment = "Production"
}
}
resource "azurestack_virtual_network" "test" {
name = "acctvn"
address_space = ["<IP_ADDRESS>/16"]
location = "${azurestack_resource_group.test.location}"
resource_group_name = "${azurestack_resource_group.test.name}"
}
resource "azurestack_subnet" "test" {
name = "acctsub"
resource_group_name = "${azurestack_resource_group.test.name}"
virtual_network_name = "${azurestack_virtual_network.test.name}"
address_prefix = "<IP_ADDRESS>/24"
}
resource "azurestack_network_interface" "test" {
name = "acctni"
location = "${azurestack_resource_group.test.location}"
resource_group_name = "${azurestack_resource_group.test.name}"
ip_configuration {
name = "testconfiguration1"
subnet_id = "${azurestack_subnet.test.id}"
private_ip_address_allocation = "dynamic"
public_ip_address_id = "${azurestack_public_ip.test.id}"
}
}
resource "azurestack_storage_account" "test" {
name = "accsa001"
resource_group_name = "${azurestack_resource_group.test.name}"
location = "${azurestack_resource_group.test.location}"
account_tier = "Standard"
account_replication_type = "LRS"
tags {
environment = "staging"
}
}
resource "azurestack_storage_container" "test" {
name = "vhds"
resource_group_name = "${azurestack_resource_group.test.name}"
storage_account_name = "${azurestack_storage_account.test.name}"
container_access_type = "private"
}
resource "azurestack_virtual_machine" "test" {
name = "acctvm"
location = "${azurestack_resource_group.test.location}"
resource_group_name = "${azurestack_resource_group.test.name}"
network_interface_ids = ["${azurestack_network_interface.test.id}"]
vm_size = "Standard_D2_v2"
# Uncomment this line to delete the OS disk automatically when deleting the VM
# delete_os_disk_on_termination = true
# Uncomment this line to delete the data disks automatically when deleting the VM
# delete_data_disks_on_termination = true
storage_image_reference {
publisher = "Canonical"
offer = "UbuntuServer"
sku = "16.04-LTS"
version = "latest"
}
# Optional data disks
storage_data_disk {
name = "datadisk0"
vhd_uri = "${azurestack_storage_account.test.primary_blob_endpoint}${azurestack_storage_container.test.name}/datadisk0.vhd"
disk_size_gb = "1023"
create_option = "Empty"
lun = 0
}
os_profile {
computer_name = "hostname"
admin_username = "testadmin"
admin_password = "Password1234!"
}
os_profile_linux_config {
disable_password_authentication = false
}
tags {
environment = "staging"
}
}
Create a VM with Public IP template - using Provider Block option
provider "azurestack" {
arm_endpoint = "https://management.{region}.{domain}"
subscription_id = "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx"
client_id = "{applicationId}@{tenantDomain}"
client_secret = "{applicationPassword}"
tenant_id = "xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx"
}
# Create a resource group
resource "azurestack_resource_group" "test" {
name = "rg01"
location = "frn00006"
}
resource "azurestack_public_ip" "test" {
name = "acceptanceTestPublicIp1"
location = "${azurestack_resource_group.test.location}"
resource_group_name = "${azurestack_resource_group.test.name}"
public_ip_address_allocation = "static"
tags {
environment = "Production"
}
}
resource "azurestack_virtual_network" "test" {
name = "acctvn"
address_space = ["<IP_ADDRESS>/16"]
location = "${azurestack_resource_group.test.location}"
resource_group_name = "${azurestack_resource_group.test.name}"
}
resource "azurestack_subnet" "test" {
name = "acctsub"
resource_group_name = "${azurestack_resource_group.test.name}"
virtual_network_name = "${azurestack_virtual_network.test.name}"
address_prefix = "<IP_ADDRESS>/24"
}
resource "azurestack_network_interface" "test" {
name = "acctni"
location = "${azurestack_resource_group.test.location}"
resource_group_name = "${azurestack_resource_group.test.name}"
ip_configuration {
name = "testconfiguration1"
subnet_id = "${azurestack_subnet.test.id}"
private_ip_address_allocation = "dynamic"
public_ip_address_id = "${azurestack_public_ip.test.id}"
}
}
resource "azurestack_storage_account" "test" {
name = "accsa001"
resource_group_name = "${azurestack_resource_group.test.name}"
location = "${azurestack_resource_group.test.location}"
account_tier = "Standard"
account_replication_type = "LRS"
tags {
environment = "staging"
}
}
resource "azurestack_storage_container" "test" {
name = "vhds"
resource_group_name = "${azurestack_resource_group.test.name}"
storage_account_name = "${azurestack_storage_account.test.name}"
container_access_type = "private"
}
resource "azurestack_virtual_machine" "test" {
name = "acctvm"
location = "${azurestack_resource_group.test.location}"
resource_group_name = "${azurestack_resource_group.test.name}"
network_interface_ids = ["${azurestack_network_interface.test.id}"]
vm_size = "Standard_D2_v2"
# Uncomment this line to delete the OS disk automatically when deleting the VM
# delete_os_disk_on_termination = true
# Uncomment this line to delete the data disks automatically when deleting the VM
# delete_data_disks_on_termination = true
storage_image_reference {
publisher = "Canonical"
offer = "UbuntuServer"
sku = "16.04-LTS"
version = "latest"
}
# Optional data disks
storage_data_disk {
name = "datadisk0"
vhd_uri = "${azurestack_storage_account.test.primary_blob_endpoint}${azurestack_storage_container.test.name}/datadisk0.vhd"
disk_size_gb = "1023"
create_option = "Empty"
lun = 0
}
os_profile {
computer_name = "hostname"
admin_username = "testadmin"
admin_password = "Password1234!"
}
os_profile_linux_config {
disable_password_authentication = false
}
tags {
environment = "staging"
}
}
How to execute a plan - using Environment Variables option
Tip
Terraform by default scans your execution directory and looks for all tf
files.
From a PowerShell prompt, navigate to the directory that contains your tf
files and run the following commands:
# Check if your environment is setup correctly
.\terraform.exe init
Initializing provider plugins...
The following providers do not have any version constraints in configuration,
so the latest version was installed.
To prevent automatic upgrades to new major versions that may contain breaking
changes, it is recommended to add version = "..." constraints to the
corresponding provider blocks in configuration, with the constraint strings
suggested below.
* provider.azurestack: version = "~> 0.1"
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
# Verify your plan
.\terraform.exe plan -var-file=C:\<DirectoryName>\testvars.tfvars
# Apply your plan
.\terraform.exe apply -var-file=C:\<DirectoryName>\testvars.tfvars
Note
You can also add -auto-approve
to the apply command for it to not ask you to apply changes for full automation.
How to execute a plan - using Provider Block option
Tip
Terraform by default scans your execution directory and looks for all tf
files.
From a PowerShell prompt, navigate to the directory that contains your tf
files and run the following commands:
# Check if your environment is setup correctly
.\terraform.exe init
Initializing provider plugins...
The following providers do not have any version constraints in configuration,
so the latest version was installed.
To prevent automatic upgrades to new major versions that may contain breaking
changes, it is recommended to add version = "..." constraints to the
corresponding provider blocks in configuration, with the constraint strings
suggested below.
* provider.azurestack: version = "~> 0.1"
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
# Verify your plan
.\terraform.exe plan
# Apply your plan
.\terraform.exe apply
Note
You can also add -auto-approve
to the apply command for it to not ask you to apply changes for full automation.
Feedback
If you find an issue with this article, click Improve this Doc to suggest a change. If you have an idea for how we could improve any of our services, visit the Ideas section of the UKCloud Community.


Shopkeeper
Sheo Shankar
<EMAIL_ADDRESS>First Link With Icon
Second Link
Subheader
Third Link With Waves


This is to be written in the near future.
This is to be written in the near future.
This is to be written in the near future.
This is to be written in the near future.
This is to be written in the near future.
This is to be written in the near future.
This is to be written in the near future.
This is to be written in the near future.


“It’s not a particularly active image, I would like to see more going on. There’s nothing here that would grab me and make me want to learn more about the product”
“The scene is very much the same as in other advertisements, it doesn’t really catch the eye”
“I’m not sure, there’s nothing wrong with the image itself, I’m just not convinced that I’d actually notice it any better than another advertisement”
“The patient and the peaceful background is a very common image in these sort of campaigns – it would not stand out from others”
“I’ve seen this basic idea so many times before; you could say this is the typical pharma advertisement”
“What am I supposed to be looking at here that I haven’t seen before? You could use this imagery in any indication and it would probably fit, there’s nothing unique about it”
“Unique? Not really. What you have here is something that is used regularly in campaigns for all sorts of drugs”
“I first notice those persons, father and son. And they seem to be playing with that ball. Everything else, doesn't become accessible initially.”
DE, Neuro
“This imagery is great…I'm just not entirely sure that I see the connection with spasticity”
FR, Neuro
“The key message is that the child is able to play for a longer interval of time. More playtime. But again, I’m seeing a little time interval here compared to the other one.”
US, Neuro
“The child looks too active, or mobile in my opinion – I don’t think this is an accurate representation of a child with the disease”
“The grandmother has to be able to move, but well, I cannot really associate funtime with spasticity in this context. I mean I cannot remember one of my patients told me that he has more fun in life now.”
DE, Neuro
“What you see is something changing, evolving, and improving over time so I think this is very relevant.”
“The concept as a whole suggests that the patient has a greater amount of time to do the things they want to do, but the headline doesn’t really fit with this idea”
“With the timeline curve at the bottom of the screen, it gets thinner towards the end – this to me suggests a lack of sustainability”
“It could just be an educational poster. The months aren’t really clear, so it could just be an ad for an educational campaign -take more time to play with your child, etc.”
FR, PM&R
“Each of the separate elements – the timeline, the imagery, the headline, they don’t fit together. The timeline suggests the product has a longer duration, but it doesn’t fit in with the idea of more playtime”
“It’s not about more funtime or more playtime, it’s about enabling the patient the complete daily activities with more independence – the headline does not match up to the rest of the concept”
“We have a little boy playing with his older brother, or father, we don’t know. More time to play. It doesn’t really speak to me.”
FR, PM&R
“The headline doesn’t really communicate a motivating message. It doesn’t really add anything to what the rest of the image is saying”
“The child looks healthier, their function and mobility seem to be increased which is of course a positive message to convey”


[Erowid Warning: Our understanding of the literature is that there is no such thing as safe use of volatile solvents, aerosols and other street inhalants : their psychoactive effects are inseparable from nerve and organ damage. We have chosen to include these reports to help document the real world use of inhalants, but their inclusion is not intended to imply that they are anything but dangerous.]
I felt most reports on duster were fairly anecdotal. My experience varied alitle from the norm and I feel compelled to express the magnitude of the feelings as best I can.
Ahh computer duster. Is there a more vile inhalent out there? I am a 19 year old with a rather dedicated drug using hobbie. I ussually enjoy all types of drugs and have tried may. Apart from habitualy weed smoking,I've dipped into opiates maybe half a dozen times, tripped off of DXM for solid months, eaten large quantities of benadryl and delved into the world of trytamines (It-190 and LSA mostly with sporadic journies to the Shroom God and Acid Lady). I can basiccally hold my brain together more-or-less while high. When I saw you could get high off of computer duster I was instantly intrigued.
The taste was sweet, the lungs felt cool (temperaturewise) for a second and then numb.  Massive tinitus struck me as my thoughts increasingly braked to a holt. I exhaled 45 seconds later and my breath felt funny, almost like my lungs were a bottle of nail polish remover. The buzz just kept hitting harder until about a minute in, were things plateaued for a little bit.
The space I was trapped in went by like hours. I thouhgt I was DEAD. I felt like I was one with the universe, but in a bad way. Very Sinister. I was an insignifgant speck that was doomed to view the universe from afar for eons until everything implodes on itself, at which point there will be blackness, but still a concious mind. When I mentally hit the blackness I kept counting to 3 in beat with my tinitus and feeling doomed because the universal language of math was stunted at 3 and therefore reality was put into suspended animation.
I felt out of phase, almost like my soul was escaping, but the grip of life was too strong. After coming down all I thought about was how interestingly weird the whole thing was, so I thought another hit wouldn't hurt, another HUGE hit. HUGE mistake, back into the void I leaped. Scared and far from my home I vowed never to touch this gas again.
It made me sick afterwards and the symptoms after contemplation felt inseperable from nerve damage. I felt dazed like when you get punched in the head real hard, thats the best way I cuould explain head buzz during the come up and comedown. The plateau is being kocked uncouncious.  The interesting thouhgt pattern and insights were abolished and forgotten by what I felt as an overall toxicity. I honestly felt DEAD. BEWARE!
Experience Reports are the writings and opinions of the individual authors who submit them.
Some of the activities described are dangerous and/or illegal and none are recommended by Erowid.


test environment
You need also open a chrome private mode window.
- Windows, Linux, or Chrome OS: Press Ctrl + Shift + n.
- Mac: Press ⌘ + Shift + n.
You need open both the original and the private window at the same time.
Also, you need make sure every window just open one tab during the test.


DIRECTED BY: John Singleton WRITTEN BY: John Singleton CAST: Samuel L. Jackson, Christian Bale, Jeffrey Wright, Toni Collette
MPAA: Rated R for strong violence and language Runtime: USA:99
RATING:7/10
In the shadow of "The X-Men", this film promises the good old fashioned action with a more believable action hero.When it comes to a character who can hold the audience's attention by the sheer power of his presence, Shaft's your man. What's most important is that "Shaft" doesn't resort to imaginative special effects in order to create a super hero, but the true human elements that are necessary for such a task. For those of you who hasn't seen the original (and in my opinion a rather overrated) version that aired in 1971, here is the story:
Shaft is the NYPD detective in charge of the investigation of a race killing.  There is one witness, a waitress named Diane (Toni Collette), and Wade warns her to keep her mouth shut... or else. Shaft makes the arrest, but the well-connected Wade is back on the streets in short order. It doesn't take long for him to jump bail and leave the country. Two years later, when he tries to sneak back in, Shaft is waiting. Meanwhile, the detective has been harassing a local drug dealer, Peoples Hernandez (Jeffrey Wright). Wade and Peoples meet in prison and thus begins an uneasy alliance to bring down Shaft.
What is true is that the theme from the original movie, which concerned racism and injustice in America, is virtually lost here, remaining nothing more than a good excuse to make a fun action film. Of course director John Singleton has included the obligatory elements of black exploitation (big cars, drugs, cigars, guns, sleazy nightclubs, gold chains, racism, babes, black leather coats, expensive booze, crooked white cops), but the problem is that all that is nothing more than props -- elements of the set decoration. Most importantly, however, "Shaft" delivers on it's promise of action, and plenty of it, and with the added benefit of having story enough to support it. Though the action sequences are not even nearly as great as in Mission: Impossible 2, they do provide a certain tension and suspense, though often descending to the kind of brainless, tiring action such as in "Gone in 60 Seconds". What is truly amazing is surprisingly the performances, especially by the three leads: Samuel Jackson, Christian Bale and Tony Colette. Unlike Wesley Snipes' ultra-cool vampire slayer in "Blade", Jackson has the physical as well as mental capabilities of being an action hero. Basically carrying the film on his shoulders, he presents enough of power, wit and strength to knock out both James Bond and Ethan Hunt out of their pedestals. However, the supporting cast is not far behind. Christian Bale puts on a spectacular performance, though his screen time is scarcely limited. Still not quite finished with Patrick Bateman from "American Psycho", he breathes life into a rather stereotypical and one-dimentional role. The third and probably one of the most amusing performances of the season, comes from Wright, who speaks with a Dominican accent so lushly indulgent it makes Al Pacino's Cuban cottonmouth in ''Scarface'' sound like a George Plimpton impersonation. What happens is that Wright takes a cliché -- the hotheaded Latin street prince -- and pushes it into operatic satire.
Shaft pushes our buttons at least as well as some of the Dirty Harry movies, which means it's something that has been next to unheard-of this year: reasonably rousing screen entertainment, but doesn't always succeed. Whatever the reason, the film is badly-focused and comes to a rather dissatisfying conclusion. Succeeding basically everywhere else, Singleton fails where others have not, by violating one of the key tenets of this sort of motion picture - that the hero should always confront (and subsequently defeat) the villain. This results in that "Shaft" fails to provide the violent catharsis that everyone in the audience is awaiting.
Though Entertainment Weekly called ''Shaft'' a "spicy fast food", I think that it is simply a series of slickly filmed action sequences dangling off a thin plot and held together by the force of Jackson's charisma.
The review above was posted to the
rec.arts.movies.reviews newsgroup (de.rec.film.kritiken for German reviews).
The Internet Movie Database accepts no responsibility for the contents of the
review and has no editorial control. Unless stated otherwise, the copyright
belongs to the author.
Please direct comments/criticisms of the review to relevant newsgroups.
Broken URLs inthe reviews are the responsibility of the author.
The formatting of the review is likely to differ from the original due
to ASCII to HTML conversion.
Related links: index of all rec.arts.movies.reviews reviews


Lloyds Banking Group: Victim Of Circumstance, Remain Cautious
by Regents ResearchSummary
- Lloyds' share price continues to flat-line as investors worry about a UK economic slowdown and the impact on the company's growth prospects.
- Revenues are in accelerated decline and this is dragging profits lower as Lloyds struggles to find enough cost savings to compensate. Profits fell by 12% YoY in 3Q.
- Lower profits are unhinging Street earnings expectations for 2020, which have fallen 10% in recent months.
- Ultimately this process will also endanger dividend estimates and undermine the yield case for the stock, which is a cornerstone of the equity story.
- On conservative assumptions I value the shares at 59p, which means there's no upside whereas the downside risks are mounting. I recommend continuing to avoid the shares.
Lloyds has been held back by UK economic certainty
I first wrote on Lloyds (NYSE: LYG) back in May (article here) when I cautioned that the persistent UK economic uncertainty brought about by Brexit was likely to weigh on the shares of this most domestic-focused of the UK banks.
This is broadly how things have panned out with Lloyds' shares being largely unchanged since that article whereas more diversified peers like Barclays (NYSE: BCS) have enjoyed a nice rally (+13%).
My view on Lloyds hasn't changed: I think it's a value-trap for as long as top-line growth is absent. It also remains much more sensitive to UK economic downside scenarios than peers. While the P/E is attractive at 8x and the dividend gives a 6% yield, Street estimates for both measures are declining, which makes current multiples potentially misleading. I would continue to avoid the shares and I would point investors to Barclays as a better way to play cheap UK bank valuations. In contrast to Lloyds, Barclays is growing, it has geographic and fx diversification and it is significantly cheaper on P/TNAV.
Lloyds' share price has suffered as Brexit uncertainty has persisted
Source: Yahoo Finance
A stalling UK economy is not good news for Lloyds
Brexit still hasn't wrought the havoc on the UK economy many feared but there has been a clear slowdown in recent quarters with 3Q YoY growth being just 1% while house prices are also at a standstill.
UK GDP growth (% YoY)
Source: Office for National Statistics
Source: Nationwide
The effect is becoming material for Lloyds as evidenced by recent results. 3Q profits were 8% below Street estimates (Reuters commentary here) driven by a 6% YoY fall in revenues. The company blamed this on lower client activity in its commercial banking business and said that headwinds were likely to persist into 4Q and 2020.
Source: company disclosures
The loss of revenue momentum is becoming progressively greater with sequential growth being negative in four of the last five quarters. 3Q revenues were 4% below their 1Q18 level over a period where Barclays, for example, has expanded its revenue base by the same percentage and posted sequential growth for three consecutive quarters.
While Lloyds lowered its FY19 cost target in the 3Q earnings announcement to try to compensate (now <£7.9bn from previously <£8bn), the reality is the company is struggling to offset the decline in revenues through efficiency measures. Operational leverage was -2% in 3Q (the difference between revenue and cost growth) putting Lloyds towards the lower end of peers.
Source: company disclosures
The revenue pressures are largely the consequence of slowing loan growth in economically-sensitive lending categories that Lloyds has targeted in recent years. Credit card volumes, for example, were 4% lower YoY in 3Q having grown 22% in FY18 while other unsecured personal credit grew by only 1% for 9m19 having expanded 6% last year.
As these higher margin lending categories rapidly come off the boil Lloyds has reentered the mortgage market that it has tended to avoid in recent years because of cut-throat price competition and its existing leadership position (c.20% market share). Mortgage volumes were 1% higher YoY in 3Q having contracted in both FY18 and FY19. The result is that Lloyds' interest margins are declining and it made a small, if symbolically significant cut to its FY margin guidance in 3Q (now ~288ps from previously ~290bps).
Source: company disclosures
ROTE remains high but is supported by cyclically low loan loss levels
In the absence of revenue growth we are left with a company that is very profitable by banking standards (ROTE was 15.4% in 3Q) but that is stagnating. Underlying profits haven't seen any growth in over two years and they fell by 12% YoY in 3Q.
Source: company disclosures
Moreover, current ROTE levels are only being achieved because loan losses are at cyclically very low levels. The 3Q "Asset Quality Ratio" (P&L provisions for loan losses/average lending balances) was 33bps and management has guided for FY19 AQR to be below 30bps.
Against this, Lloyds' 20-year average loan loss provisioning rate is 75bps and we can probably assume its "normalized" rate is higher than that now given the growth in recent years in higher-risk areas like cards and motor finance.
Source: company disclosures
A shift upwards to an AQR level of 75bps rather than the 30bps management is guiding to would reduce profits by ~25% and cut ROTE to ~10%.
On this point it's worth bearing in mind that Lloyds' AQR is already on an upward trajectory as weaker UK economic conditions start to pinch corporates and consumers. Excluding writebacks of previous loan loss provisions, new provisions for new non-performing loan exposures ("gross" AQR) have risen every quarter since 2Q18 and were 40bps in 3Q19. A more severe economic slowdown in the UK brought about by a Brexit-dislocation could quite conceivably lead to an upward step-change in Lloyds' provisioning needs.
Source: company disclosures
Falling Street earnings expectations are a big headwind for the stock
All of these issues are starting to impact Street earnings expectations. Since I last wrote on Lloyds, EPS expectations for 2020 have fallen by 10%, a big move by any standards. This undermines the cheap valuation argument for the shares since the current P/E multiple of 8x is only relevant if we get no more estimate downgrades - and this looks a brave assumption for all of the reasons I've listed above.
Source: Thomson Reuters consensus data
Falling EPS expectations also undermine the yield argument for the stock since, at a certain point, DPS expectations will also have to fall. This hasn't happened yet: 2020 DPS estimates are only 2% lower. But this just means that payout expectations have moved higher. On current Street numbers, 2020 payout will be 50% whereas the company was operating at only 30% just three years ago.
Given that the yield story is such an important component of the Lloyds equity case for many shareholders, any significant reduction in dividend expectations could wreak havoc on the share price.
Source: company data and Thomson Reuters consensus data
Conclusions
I'm instinctively wary of high yielding banking stocks since history shows that, more times than not, the yield premium closes out not because the share price goes up but because dividends come down. This is the reason I also recommend avoiding banks like ABN AMRO (OTCPK:ABNRY) and Intesa Sanpaolo (OTCPK:IITOF).
Lloyds mirrors the situation of these banks in many respects. It has attractive, dominant positions in many areas of the domestic UK retail banking market and has relatively high profitability. It is also relatively efficient. However, like these peers it is not growing, in fact its top-line is in an accelerating decline. With cost:income low (47% for 9m19) it's not obvious to me how management can stop the pressure on revenue eroding net profits. In addition, current levels of ROTE are vulnerable to a sharper than expected upward normalization of loan loss levels should the UK economy deteriorate.
The stock trades on 1.15x P/TNAV, which looks reasonable for current ROTE. Indeed if I value the stock on 2020 consensus ROTE expectations of 13% and a 10% cost of equity, then arguably fair value P/TNAV could be as high as 1.3x and the share price 20% undervalued.
However, given the dynamics, I would need a bigger buffer than this to invest in Lloyds today. Specifically I would want there to be upside even in a more bearish earnings scenario. This isn't evident. The low-point of 2020 Street consensus sees ROTE next year being 10.4%, which on the same cost of equity assumption results in a fair value share price target of 58.9p, exactly the current share price. This isn't an attractive risk-reward in my view and I will continue to avoid the shares. For investors looking to capitalize on cheap UK bank valuations I think Barclays is a much better bet, trading on just 0.6x P/TNAV and with improving operating metrics.
ROTE/COE valuation model
Source: author's calculations
Disclosure: I am/we are long BCS. I wrote this article myself, and it expresses my own opinions. I am not receiving compensation for it (other than from Seeking Alpha). I have no business relationship with any company whose stock is mentioned in this article.


(PHP 4 >= 4.0.1, PECL yaz >= 0.9.0)
yaz_wait — Wait for Z39.50 requests to complete
This function carries out networked (blocked) activity for outstanding requests which have been prepared by the functions yaz_connect(), yaz_search(), yaz_present(), yaz_scan() and yaz_itemorder().
yaz_wait() returns when all servers have either completed all requests or aborted (in case of errors).
options
An associative array of options:
Sets timeout in seconds. If a server has not responded within the timeout it is considered dead and yaz_wait() returns. The default value for timeout is 15 seconds.
A boolean.
成功时返回 TRUE
， 或者在失败时返回 FALSE
。
In event mode, returns resource 或者在失败时返回 FALSE
.


Griezmann key as France claim top spot
by BeSoccerAntoine Griezmann got a goal and an assist as Albania's first game at their new stadium ended in defeat. France beat them 0-2 in Tirana to claim first place in Group H of Euro 2020 qualifying.
On Sunday, world champions France wrapped up top spot in Group H as goals from Corentin Tolisso and Antoine Griezmann sealed a 2-0 win over Albania in Tirana.
The French national anthem was roundly booed before kick-off as retribution for the error that saw the Andorran anthem played instead of the Albanian one when the teams met in September at the Stade de France.
The visitors made a quick start on the pitch, though, as Bayern Munich midfielder Tolisso headed Griezmann's free-kick into the bottom corner.
Featured links
- Ballon d'Or winner already been decided
- The latest football transfers news and rumours
- Possible 'Clasico' in the Spanish Supercup final
- Who has the most free-kicks goals: Messi or Cristiano?
The Barcelona star slotted in the second himself on the half-hour mark, before the dead rubber petered out in the second period, with Olivier Giroud going closest to a third by striking the post.
The other games in the group saw Turkey, who had also already sealed qualification, beat Andorra 2-0, while Iceland edged to a 2-1 victory at Moldova.


First Name
Last Name
Email Address
Contact #
Add A User
First Name
Last Name
Email Address
Contact #


The Internet is a global system of interconnected computers networks that use the standard Internet protocol suite (TCP/IP) to link several billion devices worldwide. That is the definition that Wikipedia gives, but what does that really mean??
In next following paragraphs I will be explaining how to Internet works in the most layman's terms I could think of.
The Internet is a wire that is buried underground; it can be copper or fiber optic or occasionally beamed to satellite or even (what most of us do) through cellphone networks. (See figure 1)
The Internet is useful because two computers directly connected to the Internet can communicate. A Server is a special computer that is directly connected to the Internet. (See figure 2) The Webpages that everyone goes too are files on those Servers hard drives. (See figure 3)
&
Every server has a unique Internet protocol address (IP), just like a postal address. IP address help computers find each other. Since IP addresses are all numbers (<IP_ADDRESS>)... let's face it that is not really easy to remember...this is why we give them names like Google.com. (See figure 4)
Your home computer is not a server, because it is not connected directly to the Internet. Computer that you and I use are called "Clients " because they are indirectly connected to the Internet via a ISP (Internet Service Provider). (See figure 5)
Lets say you are working next to your boss and they are looking up on Marketing Research and you are on Facebook. You both are sending packets across the Internet, but what stops your boss from getting your packets instead? The solution to that problem is IP address and Routers; everything connected to the Internet has an IP address...everything! This includes your computer, servers, cellphones, and all other equipment in between. (See figure 6)
Anywhere two or more parts of the Internet intersect there is a piece of equipment called a Router. Routers direct your packet around the Internet helping each packet get one step closer to its destination. When ever you visit a website there are upwards of 10 -15 may help your packet to and from your computer. (See figure 7)
Each IP address is directly addressable, so any router can direct your packet to any other part of the Internet.


Leverage agile frameworks to provide a robust synopsis for high level overviews. Iterative approaches to corporate strategy foster collaborative thinking to further the overall value proposition. Organically grow the holistic world view of disruptive innovation via workplace diversity and empowerment.
Technology
Iterative approaches to corporate strategy foster collaborative thinking to further the overall value proposition.
Energy
Iterative approaches to corporate strategy foster collaborative thinking to further the overall value proposition.
Electricity
Iterative approaches to corporate strategy foster collaborative thinking to further the overall value proposition.
Transportation
Iterative approaches to corporate strategy foster collaborative thinking to further the overall value proposition.
Quality
Leverage agile frameworks to provide a robust synopsis for high level overviews. Iterative approaches to corporate strategy foster collaborative thinking to further the overall value proposition. Organically grow the holistic world view of disruptive innovation via workplace diversity and empowerment.


- Source:
Methods
draw()
Draw based on current state.
- Source:
texture(name, texture)
Set texture to bind to a sampler uniform.
Parameters:
| Name | Type | Description |
|---|---|---|
name |
string | Sampler uniform name. |
texture |
Texture | Texture to bind. |
- Source:
uniform(name, value)
Set the value for a uniform. Array uniforms are supported by
using appending "[0]" to the array name and passing a flat array
with all required values.
Parameters:
| Name | Type | Description |
|---|---|---|
name |
string | Uniform name. |
value |
any | Uniform value. |
- Source:
uniformBlock(name, buffer)
Set uniform buffer to bind to a uniform block.
Parameters:
| Name | Type | Description |
|---|---|---|
name |
string | Uniform block name. |
buffer |
UniformBuffer | Uniform buffer to bind. |
- Source:


Presentation to Video
My friend recorded our We Rise in Tech Conference presentations and I wanted to get them up online. I had the idea to also put our slides in the video and figured out a way to do it. Here’s a walk through of what it took to get our videos ready.
Note to future self and others: Record your slide presentation DURING your talk using your presenting tool (Keynote, PowerPoint, Google, etc.) because it makes the syncing a lot easier.
What you need
- Presentation program that allows recording of presentation (I used Keynote)
- Video recording of your presentation with audio (We used an iPhone on a tripod)
- iMovie (or Windows Movie Maker or equivalent)
Step 1 - Record your presentation slides
If you did not record your slide deck while presenting, have no fear! Just play back your video (on your phone, another computer, anywhere you can watch it) and set your presenting tool to record your presentation. Start the recording (mute the microphone if possible) and follow along with your video recording, moving through it as close as you can to the video.
Screen shots of how to record in Keynote
Record Slideshow
Start Recording and Mute Mic
Step 2 - Export recorded slides to video
I chose to export to QuickTime because I use a Mac, but if you’re on a Windows or other O/S use whatever works for you.
Step 3 - Combine in iMovie
Open iMovie and start a new project.
Drag the video of you speaking in first.
This is into the lower left hand corner of iMovie.
Drag the video of your slides above the first video.
Line it up so they start at the same time (fixable through drag and drop if you don’t get it right the first time). Make sure to not drag directly on TOP of the other video directly, it should sit above it.
Set the second video as Picture in Picture
Select the second video you dragged in (the one on top). You should see an icon with two squares on the right hand side (above the preview window). This button controls the Video Overlay Settings. Click the button and choose Picture in Picture. Size and position your slides where you want them to live for the duration of the talk.
Delete audio from one of the videos
If you recorded your presentation while you spoke, your slide recording may have audio (which will play along with your video recording). We’re going to remove whichever audio you don’t want for your final product. Select which video stream you want to delete the audio from, right click and select Detatch Audio. The Audio will appear below both video streams. You can select the audio and hit delete to remove it.
Step 4 - Tweak video alignment and settings
Lastly, watch your video and make sure it lines up (same timeline, slides change when they should) and that the volume is good. Make any adjustments here before we export.
Step 5 - Export video and upload
iMove gives quite a few options here. I chose to upload directly to YouTube, but you can also export to a video.
Hopefully this post helps you get your first presentation video online! Good luck and happy presenting :)


It would be useful to have a RMarkdown template for typical (academic) reports such as class assigments and bachelor/master thesises. The LaTeX class “report” provides a suitable format for that. This package provides a simple wrapper around this class built on the standard pandoc template.
Thanks to
Yart, ie, this package leans on earlier work by Aaron Wolen in his pandoc-letter repository, and extends it for use from R via the rmarkdown package. The structure of this package is heavily inspired by Dirk Eddenbuettel’s nice tamplate package linl.
The bulk of the work has been done by John McFarlane’s pandoc, Donald Knuth’s LaTeX, and Yihui Xie’s knitr, along with the earlier work of many.
What is yart?
Yart is a R package that provides a RMarkdown template suitable for (academic) reports. Users write basically only content with a few metadata (such as title, school’s name etc), and the template translates all that to LaTeX which is then being rendered to a PDF file.
The following screenshot shows on the left hand side the raw markdown file and on the right hand side the compiled pdf paper.
Features
Being built on Pandoc, yart provides the typical features of Pandoc’s Markdown, inculding citation, figures, tables and references thereto – and basically, via a template, the fully featured LaTeX beauty. Being built on RMarkdown/knitr, R can be knitted into the text document.
The specific add-on of this template is that it configurates a LaTeX template suitable for (academic) reports so that the user does not have to deal with the LaTeX peculiarities and can focus on writing/contents. There are a number of levers which can be adapted by the used in the yart template including author name, title, subtitle, address, date, referee’s name, assignment name, school’s name, due date.
Installation
Install via R from Github:
devtools::install_github("sebastiansauer/yart")
LaTeX needs to be installed.
Example
Skeleton
The skeleton creates a very simple letter.
Several formatting defaults are in use. See help(yart)
for a
complete list and default values.
Vignette
The vignette example is a little more featureful and shows how to include a letterhead on-demand, a signature, and a few formatting settings.
Usage
First, open as a Markdown template via RStudio via File > New File > RMarkdown > From Template > YART. The template list or Rmarkdown should feature the YART template upon the package installation:
Second, “knit” to document to pdf:
or use code such as
library(rmarkdown)
draft("my_report.Rmd", template="pdf", package="yart", edit=FALSE)
render("my_report.Rmd")
to create a first draft of a new my_report.Rmd
.
Demo video
Bugs, Feedback, Issues
Please report issues here along with a reproducible example if possible.
Related work
A number of R packages for RMarkdown templates for PDF documents are available including
Author
Sebastian Sauer
License
GPL-3 for this package, the work in pandoc-letter, as well as underlying Pandoc template.