Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Events
Videos
Audiobooks
Packt Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds

How-To Tutorials

7018 Articles
article-image-integrating-direct3d-xaml-and-windows-81
Packt
16 Jan 2014
9 min read
Save for later

Integrating Direct3D with XAML and Windows 8.1

Packt
16 Jan 2014
9 min read
(For more resources related to this topic, see here.) Preparing the swap chain for a Windows Store app Getting ready To target Windows 8.1, we need to use Visual Studio 2013. For the remainder of the article, we will assume that these can be located upon navigating to .ExternalBinDirectX11_2-Signed-winrt under the solution location. How to do it… We'll begin by creating a new class library and reusing a majority of the Common project used throughout the book so far, then we will create a new class D3DApplicationWinRT inheriting from D3DApplicationBase to be used as a starting point for our Windows Store app's render targets. Within Visual Studio, create a new Class Library (Windows Store apps) called Common.WinRT. New Project dialog to create a class library project for Windows Store apps Add references to the following SharpDX assemblies: SharpDX.dll, SharpDX.D3DCompiler.dll, SharpDX.Direct2D1.dll, SharpDX.Direct3D11.dll, and SharpDX.DXGI within .ExternalBinDirectX11_2-Signed-winrt. Right-click on the new project; navigate to Add | Existing item... ; and select the following files from the existing Common project: D3DApplicationBase.cs, DeviceManager.cs, Mesh.cs, RendererBase.cs, and HLSLFileIncludeHandlers.hlsl, and optionally, FpsRenderer.cs and TextRenderer.cs. Instead of duplicating the files, we can choose to Add As Link within the file selection dialog, as shown in the following screenshot: Files can be added as a link instead of a copy Any platform-specific code can be wrapped with a check for the NETFX_CORE definition, as shown in the following snippet: #if NETFX_CORE ...Windows Store app code #else ...Windows Desktop code #endif Add a new C# abstract class called D3DApplicationWinRT. // Implements support for swap chain description for // Windows Store apps public abstract class D3DApplicationWinRT : D3DApplicationBase { ... } In order to reduce the chances of our app being terminated to reclaim system resources, we will use the new SharpDX.DXGI.Device3.Trim function whenever our app is suspended (native equivalent is IDXGIDevice3::Trim). The following code shows how this is done: public D3DApplicationWinRT() : base() { // Register application suspending event Windows.ApplicationModel.Core .CoreApplication.Suspending += OnSuspending; } // When suspending hint that resources may be reclaimed private void OnSuspending(Object sender, Windows.ApplicationModel.SuspendingEventArgs e) { // Retrieve the DXGI Device3 interface from our // existing Direct3D device. using (SharpDX.DXGI.Device3 dxgiDevice = DeviceManager .Direct3DDevice.QueryInterface<SharpDX.DXGI.Device3>()) { dxgiDevice.Trim(); } } The existing D3DApplicationBase.CreateSwapChainDescription function is not compatible with Windows Store apps. Therefore, we will override this and create a SwapChainDescription1 instance that is compatible with Windows Store apps. The following code shows the changes necessary: protected override SharpDX.DXGI.SwapChainDescription1 CreateSwapChainDescription() { var desc = new SharpDX.DXGI.SwapChainDescription1() { Width = Width, Height = Height, Format = SharpDX.DXGI.Format.B8G8R8A8_UNorm, Stereo = false, SampleDescription.Count = 1, SampleDescription.Quality = 0, Usage = SharpDX.DXGI.Usage.BackBuffer | SharpDX.DXGI.Usage.RenderTargetOutput, Scaling = SharpDX.DXGI.Scaling.Stretch, BufferCount = 2, SwapEffect = SharpDX.DXGI.SwapEffect.FlipSequential, Flags = SharpDX.DXGI.SwapChainFlags.None }; return desc; } We will not be implementing the Direct3D render loop within a Run method for our Windows Store apps—this is because we will use the existing composition events where appropriate. Therefore, we will create a new abstract method Render and provide a default empty implementation of Run. public abstract void Render(); [Obsolete("Use the Render method for WinRT", true)] public override void Run() { } How it works… As of Windows 8.1 and DirectX Graphics Infrastructure (DXGI) 1.3, all Direct3D devices created by our Windows Store apps should call SharpDX.DXGI.Device3.Trim when suspending to reduce the memory consumed by the app and graphics driver. This reduces the chance that our app will be terminated to reclaim resources while it is suspended—although our application should consider destroying other resources as well. When resuming, drivers that support trimming will recreate the resources as required. We have used Windows.ApplicationModel.Core.CoreApplication rather than Windows.UI.Xaml.Application for the Suspending event, so that we can use the class for both an XAML-based Direct3D app as well as one that implements its own Windows.ApplicationModel.Core.IFrameworkView in order to render to CoreWindow directly. Windows Store apps only support a flip presentation model and therefore require that the swap chain is created using a SharpDX.DXGI.SwapEffect.FlipSequential swap effect; this in turn requires between two and 16 buffers specified in the SwapChainDescription1.BufferCount property. When using a flip model, it is also necessary to specify the SwapChainDescription1.SampleDescription property with Count=1 and Quality=0, as multisample anti-aliasing (MSAA) is not supported on the swap chain buffers themselves. A flip presentation model avoids unnecessarily copying the swap-chain buffer and increases the performance. By removing Windows 8.1 specific calls (such as the SharpDX.DXGI.Device3.Trim method), it is also possible to implement this recipe using Direct3D 11.1 for Windows Store apps that target Windows 8. See also The Rendering to a CoreWindow and Rendering to a SwapChainPanel recipes show how to create swap chains for non-XAML and XAML apps respectively NuGet Package Manager can be downloaded from http://visualstudiogallery.msdn.microsoft.com/4ec1526c-4a8c-4a84-b702-b21a8f5293ca You can find the flip presentation model on MSDN at http://msdn.microsoft.com/en-us/library/windows/desktop/hh706346(v=vs.85).aspx Rendering to a CoreWindow The XAML view provider found in the Windows Store app graphics framework cannot be modified. Therefore, when we want to implement the application's graphics completely within DirectX/Direct3D without XAML interoperation, it is necessary to create a basic view provider that allows us to connect our DirectX graphics device resources to the windowing infrastructure of our Windows Store app. In this recipe, we will implement a CoreWindow swap-chain target and look at how to hook Direct3D directly to the windowing infrastructure of a Windows Store app, which is exposed by the CoreApplication, IFrameworkViewSource, IFrameworkView, and CoreWindow .NET types. This recipe continues from where we left off with the Preparing the swap chain for Windows Store apps recipe. How to do it… We will first update the Common.WinRT project to support the creation of a swap chain for a Windows Store app's CoreWindow instance and then implement a simple Hello World application. Let's begin by creating a new abstract class within the Common.WinRT project, called D3DAppCoreWindowTarget and descending from the D3DApplicationWinRT class from our previous recipe. The default constructor accepts the CoreWindow instance and attaches a handler to its SizeChanged event. using Windows.UI.Core; using SharpDX; using SharpDX.DXGI; ... public abstract class D3DAppCoreWindowTarget : D3DApplicationWinRT { // The CoreWindow this instance renders to private CoreWindow _window; public CoreWindow Window { get { return _window; } } public D3DAppCoreWindowTarget(CoreWindow window) { _window = window; Window.SizeChanged += (sender, args) => { SizeChanged(); }; } ... } Within our new class, we will now override the CurrentBounds property and the CreateSwapChain function in order to return the correct size and create the swap chain for the associated CoreWindow. // Retrieve current bounds of CoreWindow public override SharpDX.Rectangle CurrentBounds { get { return new SharpDX.Rectangle( (int)_window.Bounds.X, (int)_window.Bounds.Y, (int)_window.Bounds.Width, (int)_window.Bounds.Height); } } // Create the swap chain protected override SharpDX.DXGI.SwapChain1 CreateSwapChain( SharpDX.DXGI.Factory2 factory, SharpDX.Direct3D11.Device1 device, SharpDX.DXGI.SwapChainDescription1 desc) { // Create the swap chain for the CoreWindow using (var coreWindow = new ComObject(_window)) return new SwapChain1(factory, device, coreWindow, ref desc); } This completes the changes to our Common.WinRT project. Next, we will create a Hello World Direct3D Windows Store app rendering directly to the application's CoreWindow instance. Visual Studio 2013 does not provide us with a suitable C# project template to create a non-XAML Windows Store app, so we will begin by creating a new C# Windows Store Blank App (XAML) project. Add references to the SharpDX assemblies: SharpDX.dll, SharpDX.Direct3D11.dll, SharpDX.D3DCompiler.dll, and SharpDX.DXGI.dll. Also, add a reference to the Common.WinRT project. Next, we remove the two XAML files from the project: App.xaml and MainPage.xaml. We will replace the previous application entry point, App.xaml, with a new static class called App. This will house the main entry point for our application where we start our Windows Store app using a custom view provider, as shown in the following snippet: using Windows.ApplicationModel.Core; using Windows.Graphics.Display; using Windows.UI.Core; ... internal static class App { [MTAThread] private static void Main() { var viewFactory = new D3DAppViewProviderFactory(); CoreApplication.Run(viewFactory); } // The custom view provider factory class D3DAppViewProviderFactory : IFrameworkViewSource { public IFrameworkView CreateView() { return new D3DAppViewProvider(); } } class D3DAppViewProvider : SharpDX.Component, IFrameworkView { ... } } The implementation of the IFrameworkView members of D3DAppViewProvider allows us to initialize an instance of a concrete descendent of the D3DAppCoreWindowTarget class within SetWindow and to implement the main application loop in the Run method. Windows.UI.Core.CoreWindow window;D3DApp d3dApp; // descends from D3DAppCoreWindowTarget public void Initialize(CoreApplicationView applicationView) { } public void Load(string entryPoint) { } public void SetWindow(Windows.UI.Core.CoreWindow window) { RemoveAndDispose(ref d3dApp); this.window = window; d3dApp = ToDispose(new D3DApp(window)); d3dApp.Initialize(); } public void Uninitialize() { } public void Run() { // Specify the cursor type as the standard arrow. window.PointerCursor = new CoreCursor( CoreCursorType.Arrow, 0); // Activate the application window, making it visible // and enabling it to receive events. window.Activate(); // Set the DPI and handle changes d3dApp.DeviceManager.Dpi = Windows.Graphics.Display .DisplayInformation.GetForCurrentView().LogicalDpi; Windows.Graphics.Display.DisplayInformation .GetForCurrentView().DpiChanged += (sender, args) => { d3dApp.DeviceManager.Dpi = Windows.Graphics.Display .DisplayInformation.GetForCurrentView().LogicalDpi; }; // Enter the render loop. Note that Windows Store apps // should never exit here. while (true) { // Process events incoming to the window. window.Dispatcher.ProcessEvents( CoreProcessEventsOption.ProcessAllIfPresent); // Render frame d3dApp.Render(); } } The D3DApp class follows the same structure from our previous recipes throughout the book. There are only a few minor differences as highlighted in the following code snippet: class D3DApp: Common.D3DAppCoreWindowTarget { public D3DApp(Windows.UI.Core.CoreWindow window) : base(window) { this.VSync=true; } // Private member fields ... protected override void CreateDeviceDependentResources( Common.DeviceManager deviceManager) { ... create all device resources ... and create renderer instances here } // Render frame public override void Render() { var context = this.DeviceManager.Direct3DContext; // OutputMerger targets must be set every frame context.OutputMerger.SetTargets( this.DepthStencilView, this.RenderTargetView); // Clear depthstencil and render target context.ClearDepthStencilView( this.DepthStencilView, SharpDX.Direct3D11.DepthStencilClearFlags.Depth | SharpDX.Direct3D11.DepthStencilClearFlags.Stencil , 1.0f, 0); context.ClearRenderTargetView( this.RenderTargetView, SharpDX.Color.LightBlue); ... setup context pipeline state ... perform rendering commands // Present the render target Present(); } } The following screenshot shows an example of the output using CubeRenderer, and overlaying the 2D text with the TextRenderer class: Output from the simple Hello World sample using the CoreWindow render target
Read more
  • 0
  • 0
  • 3025

article-image-article-anatomy-sprite-kit-project
Packt
16 Jan 2014
12 min read
Save for later

Anatomy of a Sprite Kit project

Packt
16 Jan 2014
12 min read
(For more resources related to this topic, see here.) A Sprite Kit project consists of things usual to any iOS project. It has the AppDelegate, Storyboard, and ViewController classes. It has the usual structure of any iOS application. However, there are differences in ViewController.view, which has the SKView class in Storyboard. You will handle everything that is related to Sprite Kit in SKView. This class will render your gameplay elements such as sprites, nodes, backgrounds, and everything else. You can't draw Sprite Kit elements on other views. It's important to understand that Sprite Kit introduces its own coordinate system. In UIkit, the origin (0,0) is located at the top-left corner, whereas Sprite Kit locates the origin at the bottom-left corner. The reason why this is important to understand is because of the fact that all elements will be positioned relative to the new coordinate system. This system originates from OpenGL, which Sprite Kit uses in implementation. Scenes An object where you place all of your other objects is the SKScene object. It represents a single collection of objects such as a level in your game. It is like a canvas where you position your Sprite Kit elements. Only one scene at a time is present on SKView. A view knows how to transition between scenes and you can have nice animated transitions. You may have one scene for menus, one for the gameplay scene, and another for the scene that features after the game ends. If you open your ViewController.m file, you will see how the SKScene object is created in the viewDidLoad method. Each SKView should have a scene, as all other objects are added to it. The scene and its object form the node tree, which is a hierarchy of all nodes present in the scene. Open the ERGMyScene.m file. Here, you can find the method where scene initialization and setup take place: - (id)initWithSize:(CGSize)size The scene holds the view hierarchy of its nodes and draws all of them. Nodes are very much like UIViews; you can add nodes as children to other nodes, and the parent node will apply its effects to all of its children, effects such as rotation or scaling, which makes working with complex nodes so much easier. Each node has a position property that is represented by CGPoint in scene coordinates, which is used to set coordinates of the node. Changing this position property also changes the node's position on the screen. After you have created a node and set its position, you need to add it to your scene node hierarchy. You can add it either to the scene or to any existing node by calling the addChild: method. You can see this in your test project with the following line: [self addChild:myLabel]; After the node has been added to a visible node or scene, it will be drawn by the scene in the next iteration of the run loop. Nodes The methods that create SKLabelNode are self-explanatory and it is used to represent text in a scene. The main building block of every scene is SKNode. Most things you can see on the screen of any given Sprite Kit game is probably a result of SKNode. Node types There are different node types that serve different purposes: SKNode: This is a parent class for different types of nodes SKSpriteNode: This is a node that draws textured sprites SKLabelNode: This is a node that displays text SKShapeNode: This is a node that renders a shape based on a Core Graphics path SKEmitterNode: This is a node that creates and renders particles SKEffectNode: This is a node that applies a Core Image filter to its children Each of them has their own initializer methods—you create one, add it to your scene, and it does the job it was assigned to do. Some node properties and methods that you might find useful are: position: This is a CGPoint representing the position of a node in its parent coordinate system. zPosition: This is a CGFloat that represents the position of a node on an imaginary Z axis. Nodes with higher zPosition will be over the nodes that have lower zPosition. If nodes have the same zPosition, the ones that were created later will appear on top of those that were created before. xScale and yScale: This is a CGFloat that allows you to change the size of any node. The default is 1.0 and setting it to any other value will change the sprite size. It is not recommended, but if you have an image of a certain resolution, scaling it will upscale the image and it will look distorted. Making nodes smaller can lead to other visual artifacts. But if you need quick and easy ways to change the size of your nodes, this property is there. name: This is the name of the node that is used to locate it in the node hierarchy. This allows you to be flexible in your scenes as you no longer need to store pointers to your nodes, and also saves you a lot of headache. childNodeWithName:(NSString *)name: This finds a child node with the specified name. If there are many nodes with the same name, the first one is returned. enumerateChildNodesWithName:usingBlock:: This allows you torun custom code on your nodes. This method is heavily used throughout any Sprite Kit game and can be used for movement, state changing, and other tasks. Actions Actions are one of the ways to add life to your game and make things interactive. Actions allow you to perform different things such as moving, rotating, or scaling nodes, playing sounds, and even running your custom code. When the scene processes its nodes, actions that are linked to these nodes are executed. To create a node, you run a class method on an action that you need, set its properties, and call the runAction: method on your node with action as a parameter. You may find some actions in the touchesBegan: method in ERGMyScene.m. In this method, you can see that a new node (of the type SKSpriteNode) is created, and then a new action is created and attached to it. This action is embedded into another action that makes it repeat forever, and then a sprite runs the action and you see a rotating sprite on the screen. To complete the preceding process, it took only five lines, and it is very intuitive. This is one of the Sprite Kit strengths—simplicity and self-documenting code. As you might have noticed, Apple names methods in a simpler way so that you can understand what it does just by reading the method. Try to adhere to the same practice and name your variables and methods so that their function can be understood immediately. Avoid naming objects a or b, use characterSprite or enemyEmitter instead. There are different action types; here we will list some that you may need in your first project: Move actions (moveTo:duration:, moveBy, followPath) are actions that move the node by a specified distance in points Rotate actions are actions that rotate your nodes by a certain angle (rotateByAngle:duration:) Actions that change node scale over time (scaleBy:duration) Actions that combine other actions (sequence: to play actions one after another, and repeatAction: to play an action a certain amount of times or forever) There are many other actions and you might look up the SKAction class reference if you want to learn more about actions. Game loop Unlike UIKit, which is based on events and waits for user input before performing any drawing or interactions, Sprite Kit evaluates all nodes, their interactions, and physics as fast as it can (capped at 60 times per second) and produces results on screen. In the following figure, you can see the way a game loop operates: First, the scene calls the update:(CFTimeInterval)currentTime method and sends it the time at which this method was invoked. The usual practice is to save the time of the last update and calculate the time that it took from the last update (delta) to the current update to move sprites by a given number of points, by multiplying the velocity of a sprite by delta, so you will get the same movement regardless of FPS. For example, if you want a sprite to move 100 pixels every second, regardless of your game performance, you multiply delta by 100. This way, if it took long to process the scene, your sprite will move slightly further for this frame; if it is processed fast, it will move just a short distance. Either way you get expected results without complex calculations. After the update is done, the scene evaluates actions, simulates physics, and renders itself on screen. This process repeats itself as soon as it's finished. This allows for smooth movement and interactions. You will write the most essential code in the update: method, since it is getting called many times per second and everything on screen happens with the code we write in this method. You will usually iterate over all objects in your scene and dispatch some job for each to do, such as character moving and bullets disappearing off screen. The update: method is not used in a template project, but it is there if you want to customize it. Let's see how we can use it to move the Hello, World! label off the screen. First, find where the label is created in the scene init method, and find this line: myLabel.text = @"Hello, World!"; Add this code right after it: myLabel.name = @"theLabel"; Find the update: method; it looks like this: - (void)update:(CFTimeInterval)currentTime Insert the following code into it: [self enumerateChildNodesWithName:@"theLabel" usingBlock:^(SKNode *node, BOOL *stop) { node.position = CGPointMake(node.position.x - 2, node.position.y); if (node.position.x < - node.frame.size.width) { node.position = CGPointMake(self.frame.size.width, node.position.y); } }]; This method first finds the child node with the name "theLabel", and as we named our label the same, it finds it and gives control to the block inside. The child that it found is a node. If it finds other nodes with the name "theLabel", it will call the same block on all of them in the order they were found. Inside the block, we change the label position by 2 pixels to the left, keeping the vertical position the same. Then, we do a check, if the position of the label from the left border of the screen is further than the length of the label, we move the label to the right-hand side of the screen. This way, we create a seamless movement that should appear to be coming out of the right-hand side as soon as the label moves off screen. But if you run the project again, you will notice that the label does not disappear. The label takes a bit longer to disappear and blinks on screen instead of moving gracefully. There are two problems with our code. The first issue is that the frame is not changing when you rotate the screen, it stays the same even if you rotate the screen. This happens because the scene size is incorrectly calculated at startup. But we will fix that using the following steps: Locate the Endless Runner project root label in the left pane with our files. It says Endless Runner, 2 targets, iOS SDK 7.0 . Select it and select the General pane on the main screen. There, find the device orientation and the checkboxes near it. Remove everything but Landscape Left and Landscape Right . We will be making our game in landscape and we don't need the Portrait mode. Next, locate your ERGViewController.m file. Find the viewDidLoad method. Copy everything after the [super viewDidLoad] call. Make a new method and add the following code: - (void) viewWillLayoutSubviews { // Configure the view. [super viewWillLayoutSubviews]; SKView * skView = (SKView *)self.view; skView.showsFPS = YES; skView.showsNodeCount = YES; // Create and configure the scene. SKScene * scene = [ERGMyScene sceneWithSize:skView.bounds.size]; scene.scaleMode = SKSceneScaleModeAspectFill; // Present the scene. [skView presentScene:scene]; } Let's see why calculations of frame size are incorrect by default. When the view has finished its load, the viewDidLoad method is getting called, but the view still doesn't have the correct frame. It is only set to the correct dimensions sometime later and it returns a portrait frame before that time. We fix this issue by setting up the scene after we get the correct frame. The second problem is the anchoring of the nodes. Unlike UIViews, which are placed on screen using their top-left corner coordinates, SKNodes are getting placed on the screen based on their anchorPoint property. The following figure explains what anchor points are. By default, the anchor point is set at (0.5, 0.5), which means that the sprite position is its center point. This comes in handy when you need to rotate the sprite, as this way it rotates around its center axis. Imagine that the square in the preceding figure is your sprite. Different anchor points mean that you use these points as the position of the sprite. The anchor point at (0, 0) means that the left-bottom corner of our sprite will be on the position of the sprite itself. If it is at (0.5, 0.5), the center of the sprite will be on the position point. Anchor points go from 0 to 1 and represent the size of the sprite. So, if you make your anchor point (0.5, 0.5), it will be exactly on sprite center. We might want to use the (0,0) anchor point for our text label. Summary In this article, we saw the different parts of the Sprite Kit project, got an idea about various objects such as scenes, nodes, and so on. Resources for Article : Further resources on this subject: Interface Designing for Games in iOS [Article] Linking OpenCV to an iOS project [Article] Creating a New iOS Social Project [Article]
Read more
  • 0
  • 0
  • 7657

article-image-securing-qlikview-documents
Packt
16 Jan 2014
6 min read
Save for later

Securing QlikView Documents

Packt
16 Jan 2014
6 min read
(For more resources related to this topic, see here.) Making documents available to the correct users can be handled in several different ways, depending on your implementation and license structure. These methods are not mutually exclusive and you may choose to implement a combination of them. By license If you only have named Document users, you can restrict access to documents by simply not granting users a license. If users do not have a Document license for a particular document, they may be able to see that document in AccessPoint, but will not be able to open it. You will need to turn off any automatic allocation of licenses for both Document licenses and Named User licenses, or the system will simply override your security by allocating an available license and giving the user access to that document. This only works for Document license users. The Named User license holders can't be locked out of a document this way as they have a license that allows them to open any number of documents, so they cannot be restricted. The fact that this is user based—a Document license can only be granted to a user, not a group—also means that there is no option to secure by a named group. This is the most basic, least flexible, and least user-friendly way to implement security. While it will certainly stop users getting access to documents—and it will work in either NTFS or DMS security modes—it can be frustrating for users to see a document that they think can open, but for which they will get a NO CAL error when they try to open it. The QlikView file will also need to have appropriate NTFS or DMS security so that users would be able to access it. The easiest way to do this is to grant access to a group that all the users will be in, or even allow access to an Authenticated Users group. Section Access Section Access security is a very effective way of securing a document to the correct set of users. This is because a user must be actually listed in the Section Access user list for the document to be even listed in AccessPoint for them. Additionally, if Section Access is in place, a user cannot even connect by using a direct access URL because they have no security access to the data. This method of securing documents works well in both NTFS and DMS security modes. When using the NTLM (Windows authentication via Internet Explorer) authentication method, you can have Group Names listed in Section Access. However, when using alternative authentication, Section Access does not give us an option to secure by group. As with the license method discussed earlier, appropriate file security needs to be in place in order to allow all the users access the QlikView file. NTFS Access Control List (ACL) NTFS (Microsoft's NT File System) security is the default method of securing access to files in a QlikView implementation. It works very well for installations where all the users are Windows users within the same domain or a set of trusted domains. In NTFS security mode, the Access Control List (ACL) of the QlikView file is used to list the documents for a particular user. This is a very straightforward way of securing access and will be very familiar to Windows system administrators. As with normal Windows file security, the security can be applied at the folder level. Windows security groups can also be used. Between groups and folder security, very flexible levels of security can be applied. By default, Internet Explorer and Google Chrome will pass through the Kerberos/NTLM credentials to sites in the local Intranet zone. For other browsers, such as Safari on the iPad, the user will be prompted for a username and password. When a user connects to AccessPoint and their credentials are established, they are compared against the ACLs for all the files hosted by QVS. Only those files that the user has access to—either directly by name or by group membership—will be listed in AccessPoint. Document Metadata Service (DMS) For non-Windows users, QlikView provides a way of managing user access to files called the Document Metadata Service (DMS). DMS uses a .META file in the same folder as the .QVW file to store the Access Control List. The Windows ACL, which has permissions on the file, now becomes mostly irrelevant as it is not used to authenticate users. It is only the QlikView service account that will need access to the file. It is a binary choice between using NTFS or DMS security on any one QlikView Server. Enabling DMS To enable DMS, we need to make a change to the server configuration. In the QlikView Management Console, on the Security tab of the QVS settings screen, we change Authorization to DMS authorization and then click on the Apply button. The QlikView Server service will need to be restarted for this change to take effect. Once the service has restarted, a new tab, Authorization, becomes available in the document properties: Clicking on the + button to the right of this tab allows you to enter new details of Access, User Type, and specific Users and Groups. Access is either set to Always or Restricted. When Access is set to Always, the associated user or group will have access at any time. If it is set to Restricted, you can specify a time range and specific days when the user or group has access. You can keep clicking on the + button to add as many sets of restricted times as needed for a user or group. The restrictions are additive; that is, if the user only has access on Monday and Tuesday in one group of restrictions, and then Thursday and Friday in another set of restrictions, they will therefore, have access on all four days. The User Type is one of the following categories: User Type Details All Users Essentially no security. Any user, including anonymous, who can access the server will be able to access the file. All Authenticated Users For most implementations, this will also be All Users. However, it will not give access to anonymous users. The Section Access would typically be used to manage the security. Named Users This allows you to specify a list of named users and/or groups that will have specific access to the document. If Named Users is selected, a Manage Users button will appear that allows you to specify users and/or groups. Summary In this article, we have looked at several ways of securing QlikView Documents—by license, using Section Access, utilizing NTFS ACLs, and implementing QlikView's DMS authorization. Resources for Article: Further resources on this subject: Common QlikView script errors [Article] Introducing QlikView elements [Article] Meet QlikView [Article]
Read more
  • 0
  • 0
  • 5587

article-image-your-first-application
Packt
15 Jan 2014
7 min read
Save for later

Your First Application

Packt
15 Jan 2014
7 min read
(For more resources related to this topic, see here.) Sketching out the application We are going to build a browsable database of cat profiles. Visitors will be able to create pages for their cats and fill in basic information such as the name, date of birth, and breed for each cat. This application will support the default Create-Retrieve-Update-Delete operations (CRUD). We will also create an overview page with the option to filter cats by breed. All of the security, authentication, and permission features are intentionally left out since they will be covered later. Entities, relationships, and attributes Firstly, we need to define the entities of our application. In broad terms, an entity is a thing (person, place, or object) about which the application should store data. From the requirements, we can extract the following entities and attributes: Cats, which have a numeric identifier, a name, a date of birth, and a breed Breeds, which only have an identifier and a name This information will help us when defining the database schema that will store the entities, relationships, and attributes, as well as the models, which are the PHP classes that represent the objects in our database. The map of our application We now need to think about the URL structure of our application. Having clean and expressive URLs has many benefits. On a usability level, the application will be easier to navigate and look less intimidating to the user. For frequent users, individual pages will be easier to remember or bookmark and, if they contain relevant keywords, they will often rank higher in search engine results. To fulfill the initial set of requirements, we are going to need the following routes in our application: Method Route Description GET / Index GET /cats Overview page GET /cats/breeds/:name Overview page for specific breed GET /cats/:id Individual cat page GET /cats/create Form to create a new cat page POST /cats Handle creation of new cat page GET /cats/:id/edit Form to edit existing cat page PUT /cats/:id Handle updates to cat page GET /cats/:id/delete Form to confirm deletion of page DELETE /cats/:id Handle deletion of cat page We will shortly learn how Laravel helps us to turn this routing sketch into actual code. If you have written PHP applications without a framework, you can briefly reflect on how you would have implemented such a routing structure. To add some perspective, this is what the second to last URL could have looked like with a traditional PHP script (without URL rewriting): /index.php?p=cats&id=1&_action=delete&confirm=true. The preceding table can be prepared using a pen and paper, in a spreadsheet editor, or even in your favorite code editor using ASCII characters. In the initial development phases, this table of routes is an important prototyping tool that forces you to think about URLs first and helps you define and refine the structure of your application iteratively. If you have worked with REST APIs, this kind of routing structure will look familiar to you. In RESTful terms, we have a cats resource that responds to the different HTTP verbs and provides an additional set of routes to display the necessary forms. If, on the other hand, you have not worked with RESTful sites, the use of the PUT and DELETE HTTP methods might be new to you. Even though web browsers do not support these methods for standard HTTP requests, Laravel uses a technique that other frameworks such as Rails use, and emulates those methods by adding a _method input field to the forms. This way, they can be sent over a standard POST request and are then delegated to the correct route or controller method in the application. Note also that none of the form submissions endpoints are handled with a GET method. This is primarily because they have side effects; a user could trigger the same action multiple times accidentally when using the browser history. Therefore, when they are called, these routes never display anything to the users. Instead, they redirect them after completing the action (for instance, DELETE /cats/:id will redirect the user to GET/cats). Starting the application Now that we have the blueprints for the application, let's roll up our sleeves and start writing some code. Start by opening a new terminal window and create a new project with Composer, as follows: $ composer create-project laravel/laravel cats --prefer-dist $ cd cats Once Composer finishes downloading Laravel and resolving its dependencies, you will have a directory structure identical to the one presented previously. Using the built-in development server To start the application, unless you are running an older version of PHP (5.3.*), you will not need a local server such as WAMP on Windows or MAMP on Mac OS since Laravel uses the built-in development server that is bundled with PHP 5.4 or later. To start the development server, we use the following artisan command: $ php artisan serve Artisan is the command-line utility that ships with Laravel and its features will be covered in more detail later. Next, open your web browser and visit http://localhost:8000; you will be greeted with Laravel's welcome message. If you get an error telling you that the php command does not exist or cannot be found, make sure that it is present in your PATH variable. If the command fails because you are running PHP 5.3 and you have no upgrade possibility, simply use your local development server (MAMP/WAMP) and set Apache's DocumentRoot to point to cats-app/public/. Writing the first routes Let's start by writing the first two routes of our application inside app/routes.php. This file already contains some comments as well as a sample route. You can keep the comments but you must remove the existing route before adding the following routes: Route::get('/', function(){   return "All cats"; }); Route::get('cats/{id}', function($id){   return "Cat #$id"; }); The first parameter of the get method is the URI pattern. When a pattern is matched, the closure function in the second parameter is executed with any parameters that were extracted from the pattern. Note that the slash prefix in the pattern is optional; however, you should not have any trailing slashes. You can make sure that your routes work by opening your web browser and visiting http://localhost:8000/cats/123. If you are not using PHP's built-in development server and are getting a 404 error at this stage, make sure that Apache's mod_rewrite configuration is enabled and works correctly. Restricting the route parameters In the pattern of the second route, {id} currently matches any string or number. To restrict it so that it only matches numbers, we can chain a where method to our route as follows: Route::get('cats/{id}', function($id){ return "Cat #$id"; })->where('id', '[0-9]+'); The where method takes two arguments: the first one is the name of the parameter and the second one is the regular expression pattern that it needs to match. Summary We have covered a lot in this article. We learned how to define routes, prepare the models of the application, and interact with them. Moreover, we have had a glimpse at the many powerful features of Eloquent, Blade, as well as the other convenient helpers in Laravel to create forms and input fields: all of this in under 200 lines of code! Resources for Article: Further resources on this subject: Laravel 4 - Creating a Simple CRUD Application in Hours [Article] Creating and Using Composer Packages [Article] Building a To-do List with Ajax [Article]
Read more
  • 0
  • 0
  • 2573

Packt
14 Jan 2014
3 min read
Save for later

Installing Virtual Desktop Agent – server OS and desktop OS

Packt
14 Jan 2014
3 min read
(For more resources related to this topic, see here.) You need to allow your Windows master image to communicate with your XenDesktop infrastructure. You can accomplish this task by installing Virtual Desktop Agent. In this latest release of the Citrix platform, VDA has been redeployed in three different versions: desktop operating systems, server operating systems, and Remote PC, a way to link an existing physical or virtual machine to your XenDesktop infrastructure. Getting ready You need to install and configure the described software with domain administrative credentials within both the desktop and server operating systems. How to do it... In the following section, we are going to explain the way to install and configure the three different types of Citrix Virtual Desktop Agents. Installing VDA for a server OS machine Connect to the server OS master image with domain administrative credentials. Mount the Citrix XenDesktop 7.0 ISO on the server OS machine by right-clicking on it and selecting the Mount option Browse the mounted Citrix XenDesktop 7.0 DVD-ROM, and double-click on the AutoSelect.exe executable file. On the Welcome screen, click on the Start button to continue. On the XenDesktop 7.0 menu, click on the Virtual Delivery Agent for Windows Server OS link, in the Prepare Machines and Images section. In the Environment section, select Create a master image if you want to create a master image for the VDI architecture (MCS/PVS). Or enable a direct connection to a physical or virtual server. After completing this step, click on Next. In the Core Components section, select a valid location to install the agent; then flag the Citrix Receiver component; and click on the Next button. In the Delivery Controller section, select Do it manually from the drop-down list in order to manually configure Delivery Controller; type a valid controller FQDN; and click on the Add button, as shown in the following screenshot. To continue with the installation, click on Next. To verify that you have entered a valid address, click on the Test connection...button. In the Features section flag, choose the optimization options that you want to enable, and then click on Next to continue, as shown in the following screenshot: In the Firewall section, select the correct radio button to open the required firewall ports automatically if you're using the Windows Firewall, or manually if you've got a firewall other than that on board. After completing this action, click on the Next button as shown in the following screenshot: If the options in the Summary screen are correct, click on the Install button to complete the installation procedure. In order to complete the procedure, you'll need to restart the server OS machine several times.
Read more
  • 0
  • 0
  • 2708

article-image-windows-azure-mobile-services-implementing-push-notifications-using
Packt
13 Jan 2014
8 min read
Save for later

Windows Azure Mobile Services - implementing push notifications

Packt
13 Jan 2014
8 min read
Understanding Push Notification Service flow The following procedure illustrates Push Notification Service (PNS) flow from establishing a channel to receiving a notification: The mobile device establishes a channel with the PNS and retrieves its handle (URI). The device registers its handle with a backend service (in our case, a table in our Mobile Service). A notification request can be made by another service, an admin system, and so on, which calls the backend service (in our case, an API). The service makes a request to the correct PNS for every device handle. The PNS notifies the device. Setting up Windows Store apps Visual Studio 2013 has a new wizard, which associates the app with the store in order to obtain a push notifications URI. Code is added to the app to interact with the service that will be updated to have a Channels table. This table has an Insert script to insert the channel and ping back a toast notification upon insert. The following procedure takes us through using the wizard to add a push channel to our app: Right-click on the project, and then navigate to Add | Push Notification. Follow the wizard and sign in to your store account (if you haven't got one, you will need to create one). Reserve an app name and select it. Then, continue by clicking on Next. Click on Import Subscriptions... and the Import Windows Azure Subscriptions dialog box will appear. Click on Download subscription file. Your default browser will be launched and the subscriptions file will be automatically downloaded. If you are logged into the portal, this will happen automatically; otherwise, you'll be prompted to log in. Once the subscription file is downloaded, browse to the downloaded file in the Import Windows Azure Subscriptions dialog box and click on Import. Select the subscription you wish to use, click on Next, and then click on Finish in the final dialog box. In the Output window in Visual Studio, you should see something like the following: Attempting to install 'WindowsAzure.MobileServices' Successfully installed NuGet Package 'WindowsAzure.MobileServices' Successfully added 'push.register.cs' to the project Added field to the App class successfully Initialization code was added successfully Updated ToastCapable in the app manifest Client Secret and Package SID were updated successfully on the Windows Azure Mobile Services portal The 'channels' table and 'insert.js' script file were created successfully Successfully updated application redirect domain Done We will now see a few things have been done to our project and service: The Package.StoreAssociation.xml file is added to link the project with the app on the store. Package.appxmanifest is updated with the store application identity. Add a push.register.cs class in servicesmobile services[Your Service Name], which creates a push notifications channel and sends the details to our service. The server explorer launches and shows us our service with a newly created table named channels, with an Insert method that inserts or updates (if changed) our channel URI. Then, it sends us a toast notification to test that everything is working. Run the app and check that the URI is inserted into the table. You will get a toast notification. Once you've done this, remove the sendNotifications(item.channelUri); call and function from the Insert method. You can do this in Visual Studio via the Server Explorer console. I've modified the script further to make sure the item is always updated, so when we send push notifications, we can send them to URIs that have been recently updated so that we are targeting users who are actually using the application (channels actually expire after 30 days too, so it would be a waste of time trying to push to them). The following code details these modifications: function insert(item, user, request) { var ct = tables.getTable("channels"); ct.where({ installationId: item.installationId }).read({ success: function (results) { if (results.length > 0) { // always update so we get the updated date var existingItem = results[0]; existingItem.channelUri = item.channelUri; ct.update(existingItem, { success: function () { request.respond(200, existingItem); } }); } else { // no matching installation, insert the record request.execute(); } } }) } I've also modified the UploadChannel method in the app so that it uses a Channel model that has a Platform property. Therefore, we can now work out which PNS provider to use when we have multiple platforms using the service. The UploadChannel method also uses a new InsertChannel method in our DataService method (you can see the full code in the sample app). The following code details these modifications: public async static void UploadChannel() { var channel = await Windows.Networking.PushNotifications. PushNotificationChannelManager. CreatePushNotificationChannelForApplicationAsync(); var token = Windows.System.Profile.HardwareIdentification. GetPackageSpecificToken(null); string installationId = Windows.Security.Cryptography. CryptographicBuffer.EncodeToBase64String(token.Id); try { var service = new DataService(); await service.InsertChannel(new Channel() { ChannelUri = channel.Uri, InstallationId = installationId, Platform = "win8" }); } catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex.ToString()); } }  Setting up tiles To implement wide or large square tiles, we need to create the necessary assets and define them in the Visual Assets tab of the Package.appxmanifest editor. This is shown in the following screenshot:  Setting up badges Windows Store apps support badge notifications as well as tile and toast. However, this requires a slightly different configuration. To implement badge notifications, we perform the following steps: Create a 24 x 24 pixel PNG badge that can have opacity, but must use only white color. Define the badge in the Badge Logo section of the Visual Assets tab of the Package.appxmanifest editor. Add a Background Tasks declaration in the Declarations tab of the Package.appxmanifest editor, select Push notification, and enter a Start page, as shown in the following screenshot: Finally, in the Notifications tab of the Package.appxmanifest editor, set Lock screen notifications to Badge. This is shown in the following screenshot: To see the badge notification working, you also need to add the app to the lock screen badge slots in Lock Screen Applications | Change PC Settings | Lock Screen.  Setting up Windows Phone 8 apps Visual Studio 2012 Express for Windows Phone doesn't have a fancy wizard like Visual Studio 2013 Express for Windows Store. So, we need to configure the channel and register it with the service manually. The following procedure sets up the notifications in the app by using the table that we created in the preceding Setting up Windows Store apps section: Edit the WMAppManifest.xml file to enable ID_CAP_IDENTITY_DEVICE, which allows us to get a unique device ID for registering in the Channels table, and ID_CAP_PUSH_NOTIFICATION, which allows push notifications in the app. These options are available in the Capabilities tab, as shown in the following screenshot: To enable wide tiles, we need to check Support for large Tiles (you can't see the tick unless you hover over it, as there is apparently a theming issue in VS!) and pick the path of the wide tile we want to use (by default, there is one named FlipCycleTileLarge.png under Tiles in the Assets folder). This is shown in the following screenshot: Next, we need to add some code to get the push channel URI and send it to the service: using Microsoft.Phone.Info; using Microsoft.Phone.Notification; using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Text; using System.Threading.Tasks; using TileTapper.DataServices; using TileTapper.Models; namespace TileTapper.Helpers { public class ChannelHelper { // Singleton instance public static readonly ChannelHelper Default = new ChannelHelper(); // Holds the push channel that is created or found private HttpNotificationChannel _pushChannel; // The name of our push channel private readonly string CHANNEL_NAME = "TileTapperPushChannel"; private ChannelHelper() { } public void SetupChannel() { try { // Try to find the push channel this._pushChannel = HttpNotificationChannel.Find(CHANNEL_NAME); // If the channel was not found, then create a new // connection to the push service if (this._pushChannel == null ) { this._pushChannel = new HttpNotificationChannel(CHANNEL_NAME); this.AttachEvents(); this._pushChannel.Open(); // Bind channel for Tile events this._pushChannel.BindToShellTile(); // Bind channel for Toast events this._pushChannel.BindToShellToast(); } else this.AttachEvents(); } catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex.ToString()); } } private void AttachEvents() { // Register for all the events before attempting to // open the channel this._pushChannel.ChannelUriUpdated + = async (s, e) => { // Register URI with service await this.Register(); }; this._pushChannel.ErrorOccurred += (s, e) => { System.Diagnostics.Debug.WriteLine(e.ToString()); }; } private async Task Register() { try { var service = new DataService(); await service.InsertChannel(new Channel() { ChannelUri = this._pushChannel.ChannelUri.AbsoluteUri, InstallationId = this.GetDeviceUniqueName(), Platform = "wp8" }); } catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex.ToString()); } } // Note: to get a result requires // ID_CAP_IDENTITY_DEVICE // to be added to the capabilities of the WMAppManifest // this will then warn users in marketplace private byte[] GetDeviceUniqueID() { byte[] result = null; object uniqueId; if (DeviceExtendedProperties.TryGetValue("DeviceUniqueId", out uniqueId)) result = (byte[])uniqueId; return result; } private string GetDeviceUniqueName() { byte[] id = this.GetDeviceUniqueID(); string idEnc = Encoding.Unicode.GetString(id, 0, id.Length); string deviceID = HttpUtility.UrlEncode(idEnc); return deviceID; } } } This is a singleton class that holds an instance of the HttpNotificationChannel object, so that channel URI changes can be captured and sent up to our service. The two methods at the end of the code snippet, GetDeviceUniqueID and GetDeviceUniqueName, will give a unique device identifier for the channels table. Now that we have the code to manage the channel, we need to call the SetupChannel method in the App.xaml.cs launching method as shown in the following code snippet: private void Application_Launching(object sender, LaunchingEventArgs e) { TileTapper.Helpers.ChannelHelper.Default.SetupChannel(); }
Read more
  • 0
  • 0
  • 3052
Unlock access to the largest independent learning library in Tech for FREE!
Get unlimited access to 7500+ expert-authored eBooks and video courses covering every tech area you can think of.
Renews at €18.99/month. Cancel anytime
article-image-thats-one-fancy-hammer
Packt
13 Jan 2014
8 min read
Save for later

That's One Fancy Hammer!

Packt
13 Jan 2014
8 min read
(For more resources related to this topic, see here.) Introducing Unity 3D Unity 3D is a new piece of technology that strives to make life better and easier for game developers. Unity is a game engine or a game authoring tool that enables creative folks like you to build video games. By using Unity, you can build video games more quickly and easily than ever before. In the past, building games required an enormous stack of punch cards, a computer that filled a whole room, and a burnt sacrificial offering to an ancient god named Fortran. Today, instead of spanking nails into boards with your palm, you have Unity. Consider it your hammer—a new piece of technology for your creative tool belt. Unity takes over the world We'll be distilling our game development dreams down to small, bite-sized nuggets instead of launching into any sweepingly epic open-world games. The idea here is to focus on something you can actually finish instead of getting bogged down in an impossibly ambitious opus. When you're finished, you can publish these games on the Web, Mac, or PC. The team behind Unity 3D is constantly working on packages and export opinions for other platforms. At the time of this writing, Unity could additionally create games that can be played on the iPhone, iPod, iPad, Android devices, Xbox Live Arcade, PS3, and Nintendo's WiiWare service. Each of these tools is an add-on functionality to the core Unity package, and comes at an additional cost. As we're focusing on what we can do without breaking the bank, we'll stick to the core Unity 3D program for the remainder of this article. The key is to start with something you can finish, and then for each new project that you build, to add small pieces of functionality that challenge you and expand your knowledge. Any successful plan for world domination begins by drawing a territorial border in your backyard Browser-based 3D – welcome to the future Unity's primary and most astonishing selling point is that it can deliver a full 3D game experience right inside your web browser. It does this with the Unity Web Player—a free plugin that embeds and runs Unity content on the Web Time for action – install the Unity Web Player Before you dive into the world of Unity games, download the Unity Web Player. Much the same way the Flash player runs Flash-created content, the Unity Web Player is a plugin that runs Unity-created content in your web browser. Go to http://unity3D.com. Click on the install now! button to install the Unity Web Player. Click on Download Now! Follow all of the on-screen prompts until the Web Player has finished installing. Welcome to Unity 3D! Now that you've installed the Web Player, you can view the content created with the Unity 3D authoring tool in your browser. What can I build with Unity? In order to fully appreciate how fancy this new hammer is, let's take a look at some projects that other people have created with Unity. While these games may be completely out of our reach at the moment, let's find out how game developers have pushed this amazing tool to its very limits. FusionFall The first stop on our whirlwind Unity tour is FusionFall—a Massively Multiplayer Online Role-Playing Game (MMORPG). You can find it at fusionfall.com. You may need to register to play, but it's definitely worth the extra effort! FusionFall was commissioned by the Cartoon Network television franchise, and takes place in a re-imagined, anime-style world where popular Cartoon Network characters are all grown up. Darker, more sophisticated versions of the Powerpuff Girls, Dexter, Foster and his imaginary friends, and the kids from Codename: Kids Next Door run around battling a slimy green alien menace. Completely hammered FusionFall is a very big and very expensive high-profile game that helped draw a lot of attention to the then-unknown Unity game engine when the game was released. As a tech demo, it's one of the very best showcases of what your new technological hammer can really do! FusionFall has real-time multiplayer networking, chat, quests, combat, inventory, NPCs (non-player characters), basic AI (artificial intelligence), name generation, avatar creation, and costumes. And that's just a highlight of the game's feature set. This game packs a lot of depth. Should we try to build FusionFall? At this point, you might be thinking to yourself, "Heck YES! FusionFall is exactly the kind of game I want to create with Unity, and this article is going to show me how!" Unfortunately, a step-by-step guide to creating a game the size and scope of FusionFall would likely require its own flatbed truck to transport, and you'd need a few friends to help you turn each enormous page. It would take you the rest of your life to read, and on your deathbed, you'd finally realize the grave error that you had made in ordering it online in the first place, despite having qualified for free shipping. Here's why: check out the game credits link on the FusionFall website: http://www.fusionfall.com/game/credits.php. This page lists all of the people involved in bringing the game to life. Cartoon Network enlisted the help of an experienced Korean MMO developer called Grigon Entertainment. There are over 80 names on that credits list! Clearly, only two courses of action are available to you: Build a cloning machine and make 79 copies of yourself. Send each of those copies to school to study various disciplines, including marketing, server programming, and 3D animation. Then spend a year building the game with your clones. Keep track of who's who by using a sophisticated armband system. Give up now because you'll never make the game of your dreams. Another option Before you do something rash and abandon game development for farming, let's take another look at this. FusionFall is very impressive, and it might look a lot like the game that you've always dreamed of making. This article is not about crushing your dreams. It's about dialing down your expectations, putting those dreams in an airtight jar, and taking baby steps. Confucius said: "A journey of a thousand miles begins with a single step." I don't know much about the man's hobbies, but if he was into video games, he might have said something similar about them—creating a game with a thousand awesome features begins by creating a single, less feature-rich game. So, let's put the FusionFall dream in an airtight jar and come back to it when we're ready. We'll take a look at some smaller Unity 3D game examples and talk about what it took to build them. Off-Road Velociraptor Safari No tour of Unity 3D games would be complete without a trip to Blurst.com—the game portal owned and operated by indie game developer Flashbang Studios. In addition to hosting games by other indie game developers, Flashbang has packed Blurst with its own slate of kooky content, including Off-Road Velociraptor Safari. (Note: Flashbang Studios is constantly toying around with ways to distribute and sell its games. At the time of this writing, Off-Road Velociraptor Safari could be played for free only as a Facebook game. If you don't have a Facebook account, try playing another one of the team's creations, like Minotaur China Shop or Time Donkey). In Off-Road Velociraptor Safari, you play a dinosaur in a pith helmet and a monocle driving a jeep equipped with a deadly spiked ball on a chain (just like in the archaeology textbooks). Your goal is to spin around in your jeep doing tricks and murdering your fellow dinosaurs (obviously). For many indie game developers and reviewers, Off-Road Velociraptor Safari was their first introduction to Unity. Some reviewers said that they were stunned that a fully 3D game could play in the browser. Other reviewers were a little bummed that the game was sluggish on slower computers. We'll talk about optimization a little later, but it's not too early to keep performance in mind as you start out. Fewer features, more promise If you play Off-Road Velociraptor Safari and some of the other games on the Blurst site, you'll get a better sense of what you can do with Unity without a team of experienced Korean MMO developers. The game has 3D models, physics (code that controls how things move around somewhat realistically), collisions (code that detects when things hit each other), music, and sound effects. Just like FusionFall, the game can be played in the browser with the Unity Web Player plugin. Flashbang Studios also sells downloadable versions of its games, demonstrating that Unity can produce standalone executable game files too. Maybe we should build Off-Road Velociraptor Safari? Right then! We can't create FusionFall just yet, but we can surely create a tiny game like Off-Road Velociraptor Safari, right? Well... no. Again, this article isn't about crushing your game development dreams. But the fact remains that Off-Road Velociraptor Safari took five supremely talented and experienced guys eight weeks to build on full-time hours, and they've been tweaking and improving it ever since. Even a game like this, which may seem quite small in comparison to full-blown MMO like FusionFall, is a daunting challenge for a solo developer. Put it in a jar up on the shelf, and let's take a look at something you'll have more success with.
Read more
  • 0
  • 0
  • 12381

article-image-using-ipv6-packet-tracer
Packt
13 Jan 2014
6 min read
Save for later

Using IPv6 on Packet Tracer

Packt
13 Jan 2014
6 min read
This article is written by Jesin A the author of Packet Tracer Network Simulator. Cisco Packet Tracer is a powerful network simulation program and provides simulation, visualization, authoring, assessment, and shows collaboration capabilities of a network. This article explains the IPv6 addresses used in Packet Tracer. IPv4 has 4.3 billion addresses, which may seem mindboggling. However, it took only two decades for it to reach its depletion. IPv6 has come to the rescue in the form of 128-bit addresses. Packet Tracer supports a wide array of IPv6 features. We'll start by learning how to assign IP addresses to different devices and how to configure routing between them. Finally, we'll create a setup that enables IPv6 communication over IPv4 devices. Assigning IPv6 addresses Starting from Packet Trace Version 6, the IP Configuration utility under the Desktop tab of end devices has an option to enter an IPv6 address. Let's begin with a simple topology consisting of two PCs and a router connected to a switch, as shown in the following screenshot: There are three ways of assigning IPv6 addresses to a device and we'll see each one of them. Autoconfiguration Autoconfiguration requires the least amount of configuration but makes it difficult to remember the IPv6 addresses. This method uses the MAC address of the device to create an IPv6 address with the FE80:: prefix. Carry out the following steps to assign IPv6 addresses using Autoconfiguration: Begin by configuring the router. Enter the interface configuration mode and enable IPv6 on the interface. R0(config)#ipv6 unicast-routing R0(config)#interface FastEthernet0/0 R0(config-if)#ipv6 enable Next, we will configure a link local address and a global unicast address on this interface. We'll use eui-64 to reduce the configuration. R0(config-if)#ipv6 address autoconfig R0(config-if)#ipv6 add 2000::/64 eui-64 R0(config-if)#no shutdown Verify that the interface is up and has two IPv6 addresses. R0>sh ipv6 interface brief FastEthernet0/0 [up/up] FE80::2D0:58FF:FE65:E701 2000::2D0:58FF:FE65:E701 These IPv6 addresses may vary when you try them out, as they are based on the MAC address. Enable routing so that this router can be identified as a default gateway. R0(config)#ipv6 unicast-routing The configuration of the router is now done, let's move on to the PCs. Go to the Desktop tab of the PC, open IP Configuration , and under the IPv6 Configuration section, choose Auto Config . The gateway and the PC's IP address will be assigned automatically, as shown in the following screenshot: Use the simple PDU tool to test the connectivity; you'll see ICMPv6 packets moving between the nodes. To view the IPv6 address from the command line of PCs, use the ipv6config command. Static IPv6 IPv6 addresses can also be assigned statically on all devices. We'll use the same topology for this section too. We'll carry out the following steps to configure IPv6 addresses statically: Begin by configuring a static IPv6 address on the router. R0(config)#interface fastethernet0/0 R0(config-if)#ipv6 enable R0(config-if)#ipv6 address 2000::1/64 R0(config-if)#no shutdown Go to the Desktop tab of PC, open the IP Configuration utility, and enter an IPv6 address with the same prefix. Now use the simple PDU tool to test the connectivity. Once both the methods work fine, you can have a look at the IPv6 neighbors table. This is similar to the ARP table of IPv4. R0#sh ipv6 neighbor IPv6 Address Age Link-layer Addr State Interface 2000::2 0 00E0.A39E.05C4 REACH Fa0/0 2000::3 0 0001.43B9.0268 REACH Fa0/0 Now that we have configured IPv6 addresses on a single network, let's configure them on more networks and enable routing between them. IPv6 static and dynamic routing Similar to IPv4, IPv6 too supports both static and dynamic routing. Configuration commands for its static routing are similar to IPv4. Static routing Modifying the same topology that we used previously, let's add a router, switch, and two PCs to create a separate network, as shown in the following screenshot: The first network will use addresses starting from 2000:1::/64 and the second network will use addresses starting from 2000:2::/64. The link between both the routers will have IP addresses 2001::10/64 and 2001::20/64. Here is a table describing the topology: Device Interface IP address R1 FastEthernet0/0 2000:1::1/64   FastEthernet0/1 2001::10/64 PC0 FastEthernet 2000:1::2/64 PC1 FastEthernet 2000:1::3/64 R2 FastEthernet0/0 2000:2::1/64   FastEthernet0/1 2001::20/64 PC2 FastEthernet 2000:2::2/64 PC3 FastEthernet 2000:2::3/64 After the necessary IP addresses and gateways have been assigned, open the CLI tab for the R1 router, and start configuring routing by following the given commands: R1(config)#ipv6 unicast-routing R1(config)#ipv6 route 2000:2::/64 2001::20 Next, open the CLI tab for R2 and configure routing on it. R2(config)#ipv6 unicast-routing R2(config)#ipv6 route 2000:1::/64 2001::10 Now use the simple PDU tool to test the connectivity. You may also use the tracert command on a PC to see the path a packet takes. PC>tracert 2000:2::3 Tracing route to 2000:2::3 over a maximum of 30 hops: 1 63 ms 63 ms 47 ms 2000:1::1 2 94 ms 78 ms 94 ms 2001::20 3 156 ms 109 ms 129 ms 2000:2::3 Trace complete. Dynamic routing Packet Tracer offers the same dynamic routing protocols for IPv6: RIPv6, EIGRP, and OSPF. We'll be configuring RIPv6 in this section. Note that RIPv6 does not represent RIP Version 6; it is RIP for IPv6 addresses. For this exercise, we'll use the topology shown in the following screenshot: The additional IP assignment details alone are shown in the following table: Device Interface IPv6 Address R2 FastEthernet1/0 2001:1::10/64 R3 FastEthernet0/0 2000:3::1/64   FastEthernet0/1 2001:1::20/64 PC2 FastEthernet 2000:3::2/64 We'll see how to configure RIP on one router and you can do the same on the others. R1(config)#interface FastEthernet0/0 R1(config-if)#ipv6 address 2000:1::1/64 R1(config-if)#ipv6 rip Net1 enable R1(config-if)#ipv6 enable R1(config-if)#interface FastEthernet0/1 R1(config-if)#ipv6 address 2001::10/64 R1(config-if)#ipv6 rip Net1 enable R1(config-if)#ipv6 enable Note that the ipv6 rip command is used to enable RIP on a particular interface. Entering ipv6 rip Net1 enable on the first interface begins the RIPv6 process. The Net1 string can be any name that can be used to name the RIP process. Once configured, use the usual diagnostic tools (ping to simple PDU) to check the connectivity. To view the RIP database, use the following command: R1#sh ipv6 rip database RIP process "Net1" local RIB 2000:2::/64, metric 2, installed FastEthernet0/1/FE80::201:97FF:FE87:E5A9, expires in 173 sec 2000:3::/64, metric 3, installed FastEthernet0/1/FE80::201:97FF:FE87:E5A9, expires in 173 sec 2001::/64, metric 2 FastEthernet0/1/FE80::201:97FF:FE87:E5A9, expires in 173 sec 2001:1::/64, metric 2, installed FastEthernet0/1/FE80::201:97FF:FE87:E5A9, expires in 173 sec RIP process "LINK" local RIB Trace the route of the packet to see the path it takes. PC>tracert 2000:3::2 Tracing route to 2000:3::2 over a maximum of 30 hops: 1 31 ms 32 ms 31 ms 2000:1::1 2 50 ms 50 ms 63 ms 2001::20 3 94 ms 94 ms 94 ms 2001:1::20 4 125 ms 109 ms 125 ms 2000:3::2 Trace complete. Summary In this article, we learned how to use IPv6 with Packet Tracer. We saw the limitation of the IPv4 addresses. We also learned how to assign IPv6 addresses and how to configure IPv6 static and dynamic routing. Resources for Article : How to edit the attributes in QGIS Troubleshooting OpenStack Compute problems Creating Identity and Resource Pools in Cisco Unified Computing System
Read more
  • 0
  • 0
  • 61806

article-image-making-poiapp-location-aware
Packt
10 Jan 2014
4 min read
Save for later

Making POIApp Location Aware

Packt
10 Jan 2014
4 min read
(For more resources related to this topic, see here.) Location services While working with location services on the Android platform, you will primarily work with an instance of LocationManager. The process is fairly straightforward as follows: Obtain a reference to an instance of LocationManager. Use the instance of LocationManager to request location change notifications, either ongoing or a single notification. Process OnLocationChange() callbacks. Android devices generally provide two different means for determining a location: GPS and Network. When requesting location change notifications, you must specify the provider you wish to receive updates from. The Android platform defines a set of string constants for the following providers: Provider Name Description GPS_PROVIDER (gps) This provider determines a location using satellites. Depending on conditions, this provider may take a while to return a location fix. This requires the ACCESS_FINE_LOCATION permission. NETWORK_PROVIDER (network) This provider determines a location based on the availability of a cell tower and Wi-Fi access points. Its results are retrieved by means of a network lookup. PASSIVE_PROVIDER (passive) This provider can be used to passively receive location updates when other applications or services request them without actually having to request for the locations yourself. It requires the ACCESS_FINE_ LOCATION permission, although if the GPS is not enabled, this provider might only return coarse fixes. You will notice specific permissions in the provider descriptions that must be set on an app to be used. Setting app permissions App permissions are specified in the AndroidManifest.xml file. To set the appropriate permissions, perform the following steps: Double-click on Properties/AndroidManifest.xml in the Solution pad. The file will be opened in the manifest editor. There are two tabs at the bottom of the screen, Application and Source, which can be used to toggle between viewing a form for editing the file or the raw XML as follows: In the Required permissions list, check AccessCoarseLocation, AccessFineLocation, and Internet. Select File | Save. Switch to the Source View to view the XML as follows: Configuring the emulator To use an emulator for development, this article will require the emulator to be configured with Google APIs so that the address lookup and navigation to map app works. To install and configure Google APIs, perform the following steps: From the main menu, select Tools | Open Android SDK Manager. Select the platform version you are using, check Google APIs, and click on Install 1 package…, as seen in the following screenshot: After the installation is complete, close the Android SDK Manager and from the main menu, select Tools | Open Android Emulator Manager. Select the emulator you want to configure and click on Edit. For Target, select the Google APIs entry for the API level you want to work with. Click on OK to save. Obtaining an instance of LocationManager The LocationManager class is a system service that provides access to the location and bearing of a device, if the device supports these services. You do not explicitly create an instance of LocationManager; instead, you request an instance from a Context object using the GetSystemService() method. In most cases, the Context object is a subtype of Activity. The following code depicts declaring a reference of a LocationManager class and requesting an instance: LocationManager _locMgr; . . . _locMgr = GetSystemService (Context.LocationService) as LocationManager; Requesting location change notifications The LocationManager class provides a series of overloaded methods that can be used to request location update notifications. If you simply need a single update, you can call RequestSingleUpdate(); to receive ongoing updates, call RequestLocationUpdate(). Prior to requesting location updates, you must identify the location provider that should be used. In our case, we simply want to use the most accurate provider available at the time. This can be accomplished by specifying the criteria for the desired provider using an instance of Android.Location.Criteria. The following code example shows how to specify the minimum criteria: Criteria criteria = new Criteria(); criteria.Accuracy = Accuracy.NoRequirement; criteria.PowerRequirement = Power.NoRequirement; Now that we have the criteria, we are ready to request updates as follows: _locMgr.RequestSingleUpdate (criteria, this, null); Summary In this article, we stepped through integrating POIApp with location services and the Google map app. We dealt with the various options that developers have to make their apps location aware and walks the reader through adding logic to determine a device's location and the address of a location, and displaying a location within the map app. Resources for Article: Further resources on this subject: Creating and configuring a basic mobile application [Article] Creating Dynamic UI with Android Fragments [Article] So, what is Spring for Android? [Article]
Read more
  • 0
  • 0
  • 4383

article-image-preparing-and-configuring-your-magento-website
Packt
10 Jan 2014
8 min read
Save for later

Preparing and Configuring Your Magento Website

Packt
10 Jan 2014
8 min read
(For more resources related to this topic, see here.) Focusing on your keywords We'll focus on three major considerations when choosing where to place our keywords within a Magento store: Purpose : What is the purpose of optimizing this keyword? Relevance : Is the keyword relevant to the page we have chosen to optimize it for? Structure : Does the structure of the website re-enforce the nature of our keyword? The purpose for choosing keywords to optimize on our Magento store must always be to increase our sales. It is true that (generically speaking) optimizing keywords means driving visitors to our website, but in the case of an e-commerce website, the end goal—the true justification of any SEO campaign—must be increasing the number of sales. We must then make sure that our visitors not just visit our website, but visit with the intention of buying something. The keywords we have chosen to optimize must be relevant to the page we are optimizing them on. The page, therefore, must contain elements specifically related to our keyword, and any unrelated material must be kept to a minimum. Driving potential customers to a page where their search term is unrelated to the content not only frustrates the visitor, but also lessens their desire to purchase from our website. The structure of our website must complement our chosen keyword. Competitive phrases, usually broader phrases with the highest search volume, are naturally the hardest to optimize. These types of keywords require a strong page to effectively optimize them. In most cases, the strength of a page is related to its level or tier within the URL. For example, the home page is normally seen as being the strongest page suitable for high search volume broad phrases followed by a tiered structure of categories, subcategories, and finally, product pages, as this diagram illustrates: With that said, we must be mindful of all three considerations when matching our keywords to our pages. As the following diagram shows, the relationship between these three elements is vital for ensuring not only that our keyword resides on a page with enough strength to enable it to perform, but also that it has enough relevance to retain our user intent at the same time as adhering to our overall purpose: The role of the home page You may be forgiven for thinking that optimizing our most competitive keyword on the home page would lead to the best results. However, when we take into account the relevance of our home page, does it really match our keyword? The answer is usually that it doesn't. In most cases, the home page should be used exclusively as a platform for building our brand identity . Our brand identity is the face of our business and is how customers will remember us long after they've purchased our goods and exited our website. In rare cases, we could optimize keywords on our home page that directly match our brand; for example, if our company name is "Wooden Furniture Co.", it might be acceptable to optimize for "Wooden Furniture" on our home page. It would also be acceptable if we were selling a single item on a single-page e-commerce website. In a typical Magento store, we would hope to see the following keyword distribution pattern: The buying intention of our visitors will almost certainly differ between each of these types of pages. Typically, a user entering our website via a broad phrase will have less of an intention to buy our products than a visitor entering our website through a more specific, product-related search term. Structuring our categories for better optimization Normally, our most competitive keywords will be classified as broad keywords, meaning that their relevance could be attributed to a variety of similar terms. This is why it makes sense to use top-level or parent categories as a basis for our broad phrases. To use our example, Wooden Furniture would be an ideal top-level category to contain subcategories such as 'Wooden Tables', 'Wooden Chairs', and 'Wooden Wardrobes', with content on our top-level category page to highlight these subcategories. On the Magento administration panel, go to Catalog | Manage Categories . Here, we can arrange our category structure to match our keyword relevance and broadness. In an ideal world, we would plan out our category structure before implementing it; sadly, that is not always the case. If we need to change our category structure to better match our SEO strategy, Magento provides a simple way to alter our category hierarchy. For example, say we currently have a top-level category called Furniture , and within this category, we have Wooden Furniture , and we decide that we're only optimizing for Wooden Furniture ; we can use Magento's drag-and-drop functionality to move Wooden Furniture to become a top-level category. To do this, we would have to perform the following steps: Navigate to Catalog | Manage Categories . Drag our Wooden Furniture category to the same level as Furniture . We will see that our URL has now changed from http://www.mydomain.com/furniture/wooden-furniture.html to http://www.mydomain.com/wooden-furniture.html. We will also notice that our old URL now redirects to our new URL; this is due to Magento's inbuilt URL Rewrite System. When moving our categories within the hierarchy, Magento will remember the old URL path that was specified and automatically create a redirect to the new location. This is fantastic for our SEO strategy as 301 redirects are vital for passing on authority from the old page to the new. If we wanted to have a look at these rewrites ourselves, we could perform the following steps: Navigate to Catalog | URL Rewrite Management . From the table, we could find our old request path and see the new target path that has been assigned. Not only does Magento keep track of our last URL, but any previous URLs also become rewritten. It is therefore not surprising that a large Magento store with numerous products and categories could have thousands upon thousands of rows within this table, especially when each URL is rewritten on a per-store basis. There are many configuration options within Magento that allow us to decide how and what Magento rewrites for us automatically. Another important point to note is that your category URL key may change depending on whether an existing category with the same URL key at the same level had existed previously in the system. If this situation occurs, an automatic incremental integer is appended to the URL key, for example, wooden-furniture-2.html. Magento Enterprise Edition has been enhanced to only allow unique URL keys. To know more, go to goo.gl/CKprNB. Optimizing our CMS pages CMS pages within Magento are primarily used as information pages. Terms and conditions, privacy policy, and returns policy are all examples of CMS pages that are created and configured within the Magento administration panel under CMS | Pages . By default, the home page of a Magento store is a CMS page with the title Home Page . The page that is served as the home page can be configured within the Magento Configuration under System | Configuration | Web | Default Pages . The most important part of a CMS page setup is that its URL key is always relative to the website's base URL. This means that when creating CMS pages, you can manually choose how deep you wish the page to exist on the site. This gives us the ability to create as many nested CMS pages as we like. Another important point to note is that, by default, CMS pages have no file extension (URL suffix) as opposed to the category and product URLs where we can specify which extension to use (if any). For CMS pages, the default optimization methods that are available to us are found within the Page Information tabs after selecting a CMS page: Under the Page Information subtab, we can choose our Page Title and URL key Under the Content subtab, we can enter our Content Heading (by default, this gets inserted into an <h1> tag) and enter our body content Under the Meta Data subtab, we can specify our keywords and description As mentioned previously, we would focus optimization on these pages purely for the intent of our users. If we were not using custom blocks or other methods to display product information, we would not optimize these information pages for keywords relating to purchasing a product. Summary In this article, we have learned the basic concepts of keyword placement and the roles of the different types of pages to prepare and configure your Magento website. Resources for Article : Further resources on this subject: Magento: Exploring Themes [Article] Magento : Payment and shipping method [Article] Integrating Twitter with Magento [Article]
Read more
  • 0
  • 0
  • 4032
article-image-aspects-data-manipulation-r
Packt
10 Jan 2014
6 min read
Save for later

Aspects of Data Manipulation in R

Packt
10 Jan 2014
6 min read
(For more resources related to this topic, see here.) Factor variables in R In any data analysis task, the majority of the time is dedicated to data cleaning and pre-processing. Sometimes, it is considered that about 80 percent of the effort is devoted for data cleaning before conducting actual analysis. Also, in real world data, we often work with categorical variables. A variable that takes only a limited number of distinct values is usually known as a categorical variable, and in R, this is known as a factor. Working with categorical variables in R is a bit technical, and in this article we have tried to demystify this process of dealing with categorical variables. During data analysis, sometimes the factor variable plays an important role, particularly in studying the relationship between two categorical variables. In this section, we will see some important aspects of factor manipulation. When a factor variable is first created, it stores all its levels along with the factor. But if we take any subset of that factor variable, it inherits all its levels from the original factor levels. This feature sometimes creates confusion in understanding the results. Numeric variables are convenient during statistical analysis, but sometimes we need to create categorical (factor) variables from numeric variables. We can create a limited number of categories from a numeric variable using a series of conditional statements, but this is not an efficient way to perform this operation. In R, cut is a generic command to create factor variables from numeric variables. Split-apply-combine strategy Data manipulation is an integral part of data cleaning and analysis. For large data it is always preferable to perform the operation within subgroup of a dataset to speed up the process. In R this type of data manipulation could be done with base functionality, but for large-scale data it requires considerable amount of coding and eventually it takes a longer time to process. In case of Big Data we could split the dataset, perform the manipulation or analysis, and then again combine the results into a single output. This type of split using base R is not efficient and to overcome this limitation, Wickham developed an R package plyr where he efficiently implemented the split-apply-combine strategy. Often, we require similar types of operations in different subgroups of a dataset, such as group-wise summarization, standardization, and statistical modeling. This type of task requires us to break up a big problem into manageable pieces, perform operations on each piece separately, and finally combine the output of each piece into a single piece of output. To understand the split-apply-combine strategy intuitively, we could compare this with the map-reduce strategy for processing large amounts of data, recently popularized by Google. In the map-reduce strategy, the map step corresponds to split and apply and the reduce step consists of combining. The map-reduce approach is primarily designed to deal with a highly parallel environment where the work has been done by several hundreds or thousands of computers independently. The split-apply-combine strategy creates an opportunity to see the similarities of problems across subgroups that were previously unconnected. This strategy can be used in many existing tools, such as the GROUP BY operation in SAS, PivotTable in MS Excel, and the SQL GROUP BY operator. Reshaping a dataset Reshaping data is a common and tedious task in real-life data manipulation and analysis. A dataset might come with different levels of grouping and we need to implement some reorientation to perform certain types of analyses. Datasets layout could be long or wide. In long-layout, multiple rows represent a single subject's record, whereas in wide-layout, a single row represents a single subject's record. Statistical analysis sometimes requires wide data and sometimes long data, and in such cases, we need to be able to fluently and fluidly reshape the data to meet the requirements of statistical analysis. Data reshaping is just a rearrangement of the form of the data—it does not change the content of the dataset. In this article, we will show you different layouts of the same dataset and see how they can be transferred from one layout to another. This article mainly highlights the melt and cast paradigm of reshaping datasets, which is implemented in the reshape contributed package. Later on, this same package is reimplemented with a new name, reshape2, which is much more time and memory efficient. A single dataset can be rearranged in many different ways, but before going into rearrangement, let's look back at how we usually perceive a dataset. Whenever we think about any dataset, we think of a two-dimensional arrangement where a row represents a subject's (a subject could be a person and is typically the respondent in a survey) information for all the variables in a dataset and a column represents the information for each characteristic for all subjects. This means rows indicate records and columns indicate variables, characteristics, or attributes. This is the typical layout of a dataset. In this arrangement, one or more variables might play a role as an identifier and others are measured characteristics. For the purpose of reshaping, we could group the variables into two groups: identifier variables and measured variables. Identifier variables: These help to identify the subject from whom we took information on different characteristics. Typically, identifier variables are qualitative in nature and take a limited number of unique values. In database terms, an identifier is termed as the primary key, and this can be a single variable or a composite of multiple variables. Measured variables: These are those characteristics whose information we took from a subject of interest. These can be qualitative, quantitative, or a mix of both. Now beyond this typical structure of dataset, we could think differently, where we will have only identification variables and a value. The identification variable identifies a subject along with which measured variable the value represents. In this new paradigm, each row represents one observation of one variable. In the new paradigm this is termed as melting and it produces molten data. The difference between this new layout of the data and the typical layout is that it now contains only the ID variable and a new column, value, which represents the value of that observation. Summary This article explains briefly about factor variables, the split-apply-combine strategy, and reshaping a dataset in R. Resources for Article: Further resources on this subject: SQL Server 2008 R2: Multiserver Management Using Utility Explorer [Article] Working with Data Application Components in SQL Server 2008 R2 [Article] Customizing Graphics and Creating a Bar Chart and Scatterplot in R [Article]
Read more
  • 0
  • 0
  • 7172

article-image-unleashing-your-development-skills-powershell
Packt
09 Jan 2014
11 min read
Save for later

Unleashing Your Development Skills with PowerShell

Packt
09 Jan 2014
11 min read
(For more resources related to this topic, see here.) Windows PowerShell is a game changer in the shell scripting and automation world. This is not only because it is an object-based scripting language that is built on top of the .NET framework but also because it unifies a lot of different scripting and automation tools in one single, consistent, and dynamic engine. By leveraging the same engine and language you can deal with various amazing technologies such as Windows Management Instrumentation (WMI), Common Information Model (CIM), and Component Object Model (COM). Moreover, you can use it to build an automation interface for the applications you develop. In this article, we will go deeper into Windows PowerShell to understand what are the different technologies that can be managed by Windows PowerShell, learn how to do it, and discover more advanced scripting techniques obtained from your current development skills. Understanding CIM and WMI CIM is an open standard defined by the Distributed Management Task Force (DMTF) as part of the Web-Based Enterprise Management (WBEM) initiative. CIM is used to define an extensible data model that describes, processes, and obtains the characteristic information of managed resources such as hardware components and software. CIM is a programming model that is object oriented and manufacture independent, which means that you can manage different resources from different vendors by just using the CIM standard. On the other side, WMI is a Microsoft implementation of CIM that is introduced in Windows 2000 to allow the management of all Windows software and hardware components. CIM and WMI in Windows PowerShell Windows PowerShell v2.0 has been shipped with a few cmdlets to support and work with WMI as a middle layer between the end user (system administrators and developers) and CIM. Later on, in Windows PowerShell v3.0, a new direct support to CIM was introduced via more cmdlets with Windows Server 2012 and Windows 8, which allows PowerShell users to directly expose the CIM schema and data model. To retrieve the list of cmdlets for WMI and CIM, we will use the Get-Command cmdlet with the -Name parameter filtered by a wildcard and the -Type parameter, filtered by a cmdlet argument to get only the cmdlets and not functions or aliases, as shown in the following snippet: #List all WMI available Cmdlets PS C:> Get-Command *WMI* -Type Cmdlet CommandType Name ModuleName ----------- ---- ---------- Cmdlet Get-WmiObject Microsoft.PowerShell.Management Cmdlet Invoke-WmiMethod Microsoft.PowerShell.Management Cmdlet Register-WmiEvent Microsoft.PowerShell.Management Cmdlet Remove-WmiObject Microsoft.PowerShell.Management Cmdlet Set-WmiInstance Microsoft.PowerShell.Management #List all CIM available Cmdlets PS C:> Get-Command *CIM* -Type Cmdlet CommandType Name ModuleName ----------- ---- ---------- Cmdlet Get-CimAssociatedInstance CimCmdlets Cmdlet Get-CimClass CimCmdlets Cmdlet Get-CimInstance CimCmdlets Cmdlet Get-CimSession CimCmdlets Cmdlet Invoke-CimMethod CimCmdlets Cmdlet New-CimInstance CimCmdlets Cmdlet New-CimSession CimCmdlets Cmdlet New-CimSessionOption CimCmdlets Cmdlet Register-CimIndicationEvent CimCmdlets Cmdlet Remove-CimInstance CimCmdlets Cmdlet Remove-CimSession CimCmdlets Cmdlet Set-CimInstance CimCmdlets Now, after getting the list of both cmdlets for CIM and WMI, take a few seconds for looking at each cmdlet. Did you notice it? Yes, there are CIM cmdlets similar to WMI cmdlets, which makes sense because, as we said earlier, WMI is an implementation of CIM. Although both the cmdlet sets look the same and show almost the same results, you will find that the CIM-related cmdlets have more parameters and there are even more cmdlets than in WMI in order to provide you with more information. CIM and WMI represent the provided information in the form of namespaces and classes. For example, there is a class for BIOS called Win32_BIOS, and another one for the operating system called Win32_OperatingSystem. There are other classes that start with _, such as _CLASSNAME for internal operating system usage and CIM_CLASSNAME for some basic classes, but the classes that are mostly used are the ones that start with the prefix Win32_CLASSNAME. In case you do not know the name of a class or want to discover the list of available classes in your system, you can use either the Get-WmiObject –List cmdlet or the Get-CimClass cmdlet to retrieve the same results. #List available classes using WMI PS C:> Get-WmiObject –Class * -List #List available classes using CIM PS C:> Get-CimClass –ClassName * Win32_CurrentTime Win32_LocalTime Win32_OperatingSystem Win32_Process Win32_ComputerSystem Win32_BIOS Win32_SoftwareElement (...) #Comparing the number of classes retrieved by each cmdlet PS C:> (Get-WmiObject -List).count -eq (Get-CimClass).count True After knowing which class you want to use, you have to create an instance of this class to get whatever information is provided by it. For this purpose, you can use either the Get-WmiObject cmdlet or the Get-CimInstance cmdlet and define the class name as a parameter. #Get class instance using WMI PS C:> Get-WmiObject -Class Win32_BIOS #Create class instance using CIM PS C:> Get-CimInstance -ClassName Win32_BIOS SMBIOSBIOSVersion : 8BET59WW (1.39 ) Manufacturer : LENOVO Name : Default System BIOS SerialNumber : R9T081V Version : LENOVO – 1390 You can also use –Query as a parameter instead of a class name to execute a predefined WMI query written in WMI Query Language (WQL). #Building WQL query to read from Win32_NetworkAdapter class PS C:> $Query = "Select * From Win32_NetworkAdapter Where Name like '%Intel%'" #Execute the WQL query using WMI PS C:> Get-WmiObject -Query $Query | Select DeviceID, Name #Execute the WQL query using CIM PS C:> Get-CimInstance -Query $Query | Select DeviceID, Name DeviceID Name -------- ---- 0 Intel(R) 82579LM Gigabit Network Connection 2 Intel(R) Centrino(R) Ultimate-N 6300 AGN You can follow the same steps as in the previous example when you want to remove an instance. Use the Remove-WmiObject and Remove-CimInstance cmdlets as well as Set-WmiInstance and Set-CimInstance when you want to update an existing instance. The following simple example will show how we can use the Get-WmiObject and Remove-WmiObject cmdlets together to get a specific directory information in a WMI instance, and then delete it: #Get a directory called "myOldBackup' $folder = Get-WmiObject -Class Win32_Directory -Filter "Name='D:\ myOldBackup'" #Remove (delete) the folder $folder | Remove-WmiObject Other interesting cmdlets are Register-CimIndicationEvent and Register-WmiEvent; both these cmdlets allow you to trigger an action within a PowerShell scriptblock according to a predefined WMI or CIM event criteria. For example, you can trigger a notification message when the CPU utilization exceeds 85 percent or when a specific service stopped. More reasons to adopt CIM Well, after understanding what is WMI and CIM and exploring a few cmdlets with many similarities from both sides, you have to admit that you are getting confused and wondering why new CIM cmdlets have been introduced and why use them if WMI cmdlets were fine in the previous versions of Windows PowerShell. To answer this question and avoid any philosophical debates, let's discover what makes CIM an added value and feature to PowerShell using the following points: It is an open standard, which means that it is not locked into the Windows operating system only, so that you can use CIM to manage other vendors and manufacturers. It uses WS-Management (WS-MAN) protocol for remote management so that you can use it with any remote server or device implementing this protocol. However, WMI is used to manage only Windows over the DCOM protocol. It can be used with Open Management Infrastructure (OMI) compliant devices. Read more about OMI from the following article: http://blogs.technet.com/b/windowsserver/archive/2012/06/28/open-management-infrastructure.aspx It can be used to manage any computer or device with an operating system that has the CIM Object Manager (CIMOM) compliance implemented irrespective of the vendor. So, you can use CIM to manage Windows as well as non-Windows operating systems. Working with XML XML parsing and formatting is one of the most commonly used functionalities in application development. PowerShell provides built-in support for XML in a smart way that allows you to work with XML files easily with minimal lines of code. This is enough to make PowerShell your perfect choice for daily XML tasks and operations. Loading XML files There are two ways to load an XML file in PowerShell—either using the Get-Content cmdlet or using the Select-Xml cmdlet with the XPath queries. Using the Get-Content cmdlet In order to load and read the content of a file in PowerShell, we use the Get-Content cmdlet; this cmdlet is used to load content from text as well as XML files, which are text files written in a structured, descriptive format so that the Get-Content cmdlet can be used to load the XML files too. #Load file content using Get-Content PS C:> Get-Content C:Employees.xml The previous lines will load the content of the XML file as normal text. So, in order to make PowerShell understand that this is an XML file, we have to either cast the results of the Get-Content cmdlet or store the output in a strongly typed variable of XML data type, as shown in the following examples: #results casting $employee = [xml](Get-Content D:Employees.xml) #Store results in XML variable [xml] $employees = Get-Content D:Employees.xml The strongly typed variables, such as [xml] $employees, can be assigned only with a System.Xml.XmlDocument type of object. Otherwise, they will trigger an error. The following code shows a sample of the employee.xml file's structure: <staff> <branch location="cairo"> <employee> <Name>Sherif Talaat</Name> <Role>IT</Role> </employee> </branch> </staff> The XML file that is loaded has information about the staff members in different branches with different specialties. Now, we have the content of the file stored in a variable called $employees that can be accessed normally like any other object along with XML capabilities, as shown in the following examples: #Access child nodes of XML documentsPS C:> $employees.staff.ChildNodeslocation employee-------- --------cairo {Sherif Talaat, Raymond Elias}redmond {Bill Gates, Steve Jobs}#Get attributes information of a nodePS C:> $employees.staff.branch.Get_Attributes()#text-----cairoRedmond#Get attributes value by Attribute namePS C:> $employees.staff.branch. locationcairoRedmond#Change the value of attributePS C:> $employees.staff.branch[0]. location= 'Seattle'#Change and Modify Single nodePS C:> $employees.staff.branch.employeeName Role---- ----Sherif Talaat ITRaymond Elias Technology SpecialistPS C:> $emp = $employees.staff.branch.employee[0]PS C:> $emp.Role = "PowerShell Guru"PS C:> $employees.SelectNodes("//employee[Name='Sherif Talaat']")Name Role---- ----Sherif Talaat PowerShell Guru#add new nodePS C:> $newemployee = $employees.CreateElement("employee")PS C:> $newemployee.set_InnerXML("<Name>Ahmad Mofeed</Name><Role>Security Consultant</Role>")PS C:> $employees.staff.branch[0].AppendChild($newemployee)PS C:> $employees.staff.branch[0].employeeName Role---- ----Sherif Talaat PowerShell GuruRaymond Elias Technology SpecialistAhmad Mofeed Security Consultant Using the Select-Xml cmdlet Another way to load and work with XML files is using the Select-Xml cmdlet that allows you to directly specify the XML file path along with an XPath search query to retrieve the respective node and data, as shown in the following snippet: #Get data from XML file using XPath query PS C:> Select-Xml -Path D:Employees.xml -XPath "staff/branch/ employee" Node Path Pattern ---- ---- ------- employee D:Employees.xml staff/branch/employee employee D:Employees.xml staff/branch/employee employee D:Employees.xml staff/branch/employee In the previous example, the Select-Xml cmdlet was used to retrieve XML nodes using the XPath search query; the result is an object of nodes with no values. To expand these nodes and enumerate their values, we have to use the Select-Object cmdlet with the -ExpandProperty parameter. PS C:> Select-Xml -Path D:Employees.xml -XPath "staff/branch/ employee" | Select-Object -ExpandProperty Node Name Role ---- ---- Sherif Talaat IT Raymond Elias Technology Specialist Bill Gates Developer Importing and exporting XML files PowerShell also provides a couple of XML-related cmdlets—the Export-CliXml cmdlet to export the object(s) to an XML file and Import-CliXml to import and load the file that was previously exported by PowerShell, as shown in the following snippet: #Export object to XML file PS C:> Get-Service | Export-Clixml D:Services.xml #Import object from XML file PS C:> Import-Clixml D:Services.xml -First 5 Status Name DisplayName ------ ---- ----------- Running AdobeARMservice Adobe Acrobat Update Service Stopped AeLookupSvc Application Experience Stopped ALG Application Layer Gateway Service Running AppIDSvc Application Identity Running Appinfo Application Information Moreover, you also have the ConvertTo-Xml cmdlet that is similar to the Export-CliXml cmdlet, where both the cmdlets create an XML representation of one or more objects. The only difference is that the Export-CliXml cmdlet stores the XML code in a file while the ConvertTo-Xml cmdlet returns an XML object that can be used as an input to another cmdlet. Summary In this article, we learned how to use Windows PowerShell to work closely with WMI, COM, and XML. Resources for Article: Further resources on this subject: Using the Windows Azure Platform PowerShell Cmdlets [Article] How to use PowerShell Web Access to manage Windows Server [Article] Exchange Server 2010 Windows PowerShell: Working with Address Lists [Article]
Read more
  • 0
  • 0
  • 4605

article-image-time-saving-features-zsh
Packt
09 Jan 2014
7 min read
Save for later

Time Saving Features of Zsh

Packt
09 Jan 2014
7 min read
(for more resources related to this topic, see here.) Working with history Like an elephant, many modern Unix shells tend to remember in great detail the copious amount of commands entered while working with them. Being able to glimpse at what you have been up to is not only practical from a work-log perspective, but also as a way to speed things up. Think about it; you could use history to see (and eventually edit) a previously typed command, get a bit of context as to what's going on with your system, or avoid retyping the same thing over and over. We'll now take a look at how to use zsh's history expansion to work with previous entries in the command line. History expansion One of the ways zsh provides for you to access your history is via the so-called history expansion. This works whenever your input begins with the bang ! special character. Accessing your history entries is done via what we call event designators. Like escape sequences, designators are fancy names for constructs that the shell expands in order to know exactly what needs to be retrieved from history. One of the most popular and helpful event designators is the double bang (!!), which by itself refers to the most recent command entered: % sh myscript.sh > myscript.sh: Error: you need to be root to execute this. % sudo !! > myscript.sh: executing myscript.sh As you can see, the !! character can be really useful for those occasions when you forget to run something on elevated privileges. What happens then is that zsh immediately expands the reference to the last command in history and replaces it in the line that contains the sudo call, saving you from entering the whole line again. That's really neat for the command we just typed, but what if the previous command is further behind in the history timeline? Well, then we need to use the vanilla event bang: % !cat % cat /etc/hosts | grep 127.0.1.1 Here my last executed command that had cat in it was a printout of my hosts file (cat /etc/hosts), followed by a call to grep as I was looking for lines that have 127.0.1.1 on them. If you connect to a remote host using SSH, you could use something like the following to retrieve the last run connection: % !ssh % ssh gfestari@192.168.1.10 As you can see, the syntax for history expansion is fairly easy to remember. Just put a ! character together with the command you're looking for and let zsh work its magic. Having the shell making substitutions and automatically executing commands demands a bit more "blind faith" than most of us would like to deposit on their shell. Luckily, we can set the HIST_VERIFY option in .zshrc to force zsh into asking for confirmation every time you bang a command: % setopt HIST_VERIFY % echo 'Hello!' > Hello! % !! % echo 'Hello!' The shell completes the input in your prompt using the previous command, but does not execute it. This is really useful for things like elevated privileges or sudo commands. Feel free to go ahead and add setopt HIST_VERIFY to your .zshrc file, as we'll assume it is being used from now on. Let's kick it up a notch then; you can combine the special characters ^ and $ in order to access the first and last arguments of a history entry respectively: % mkdir new_folder % cd !^ % cd new_folder The ^ character gets expanded into the first argument of the mkdir command, which in this particular case is new folder. % touch log1.txt log2.txt % nano !$ % nano log2.txt Here the same happens with $, only this time the last argument of the touch command is expanded so we can eventually edit it using nano. If you are familiar with regular expressions, both of these designators' behavior shouldn't be too surprising. However, if what you need to do is access some string that is not located either at the beginning (^) or end ($) of the history, then you need the ? designator: % !?etc > cat /etc/hosts | grep 127.0.1.1 The preceding expression matches the most recent command containing etc. Generally speaking, the syntax for using the ? event designator can then be summed up as follows: !?str[?] The optional ? you see there at the end is only necessary if the command is followed by any text that is not to be considered part of str; for example: % !?etc?^ > /etc/hosts Did you notice how both the ? characters serve as delimiters for the etc keyword? Think of them as parentheses that wrap the expression you're trying to match. The caret operator (^) is there as we are interested in the first argument of that particular command line, which coincidentally is the /etc/hosts string. There's lots more we can do with the history bang operator. Another neat trick is that it can refer to a particular line in your history. As before, the syntax is merely a tweak of what we already know: !<hist_number> % !103 # this retrieves the 103rd entry in your $HISTFILE. % !4 # this retrieves the 4th entry. But what about knowing which line I want to use? Well, that's a bit more complex, but not as much as using grep, ack, or whatever it is that kids are using these days to search within your history file: % history | grep nano > 2045 nano /etc/hosts Using grep and searching for entries that feature nano, I can see that I edited /etc/hosts with it, and that the record resides on line 2045 of my $HISTFILE. If we wanted to open the hosts file again, it'll be a simple matter of calling: % !2045 % nano /etc/hosts Interestingly, you can also use a negative integer to refer to the nth-to-last entry: % !-2 # this will retrieve the 2nd to last entry in history. % !-97 # this does the same to the 97th to last entry. Negative indexes should be pretty familiar territory for some programmers (I'm looking at you, Python and Ruby developers). You can prevent a command from being added to your history by setting HIST_IGNORE_SPACE in your startup files. This will make the shell ignore the lines that start with a space. % echo "this line will be recorded in history" % echo "this will not" More useful options Here are a couple of history-related options worth considering when populating your startup files, in addition to what we have already discussed. Just put any (or all) of these on your .zshrc and remember to append setopt before each entry. EXTENDED_HISTORY: Saves a timestamp and duration for each history entry run. An excellent addition for the data analysis aficionado. HIST_IGNORE_ALL_DUPS: Ignores duplicate entries when showing results. HIST_FIND_NO_DUPS: Does not display eventual duplicates of a line that has already been found. HIST_REDUCE_BLANKS: Removes extra spaces and tabs from history entries. INC_APPEND_HISTORY: Adds entries to the history as they are typed, that is, doesn't wait until the shell exits. Probably one of the most awesome features of zsh. You know you want this. SHARE_HISTORY: Shares history between different zsh processes. Another great option to compliment the previous entry. Summary So we had a look at some of the most prominent time-saving features of zsh by learning about history expansion and to avoid repeating ourselves into oblivion. We went beyond using the Up and Down arrow keys and applied some more specific constructs such as the double bang (!!) to recall the very last entry of our log. Not bad at all. Pat yourself in the back or go grab a beer. Although, come to think about it, there seems to be much more left in store for us to discover yet… Resources for article: further resources on this subject: Linux Shell Scripting – various recipes to help you [article] Installing VirtualBox on Linux [article] Linux Shell Script: Monitoring Activities [article]
Read more
  • 0
  • 0
  • 2308
article-image-marionette-view-types-and-their-use
Packt
07 Jan 2014
15 min read
Save for later

Marionette View Types and Their Use

Packt
07 Jan 2014
15 min read
(For more resources related to this topic, see here.) Marionette.View and Marionette.ItemView The Marionete.View extends the Backbone.View, and it's important to remember this, because all the knowledge that we already have on creating a view will be useful while working with these new set of views of Marionette. Each of them aims to provide a specific out of the box functionality so that you spend less time focusing on the glue code needed to make things work, and more time on things that are related to the needs of your application. This allows you to focus all your attention on the specific logic of your application. We will start by describing the Marionette.View part of Marionette, as all of the other views extend from it; the reason we do this is because this view provides a very useful functionality. But it's important to notice that this view is not intended to be used directly. As it is the base view from which all the other views inherit from, it is an excellent place to contain some of the glue code that we just talked about. A good example of that functionality is the close method, which will be responsible for removing .el from DOM. This method will also take care of calling unbind to all your events, thus avoiding the problem called Zombie views. This an issue that you can have if you don't do this carefully in a regular Backbone view, where new instantiations of previously closed fire events are present. These events remain bound to the HTML elements used in the view. These are now present again in the DOM now that the view has been rerendered, and during the recreation of the view, new event listeners are attached to these HTML elements. From the documentation of the Marionette.View, we exactly know what the close method does. It calls an onBeforeClose event on the view, if one is provided It calls an onClose event on the view, if one is provided It unbinds all custom view events It unbinds all DOM events It removes this.el from the DOM It unbinds all listenTo events The link to the official documentation of the Marionette.View object is https://github.com/marionettejs/backbone.marionette/blob/master/docs/marionette.view.md. It's important to mention that the third point, unbind all custom view events, will unbind events created using the modelEvents hash, those created on the events hash, and events created via this.listenTo. As the close method is already provided and implemented, you don't need to perform the unbind and remove previously listed tasks. While most of the time this would be enough, at times, one of your views will need you to perform extra work in order to properly close it; in this case, two events will be fired at the same time to close a view. The event onBeforeClose, as the name indicates, will be fired just before the close method. It will call a function of the same name, onBeforeClose, where we can add the code that needs to be executed at this point. function : onBeforeClose () { // code to be run before closing the view } The second event will be onClose, which will be fired after the close method so that the .el of the view won't be present anymore and all the unbind tasks will have been performed. function : onClose () { // code to be run after closing the view } One of the core ideas behind Marionette is to reduce the boilerplate code that you have to write when building apps with Backbone. A perfect example of which is the render method that you have to implement in every Backbone view, and the code there is pretty much the same in each of your views. Load the template with the underscore _.template function and then pass the model converted to JSON to the template. The following is an example of repetitive code needed to render a view in Backbone: render : function () { var template = $( '#mytemplate' ).html(); var templateFunction = _.template( template ); var modelToJSON = this.model.toJSON(); var result = templateFunction(modelToJSON); var myElement = $( '#MyElement' ); myElement.html( result ); } As Marionette defining a render function is no longer required, just like the close method, the preceding code will be called for you behind the scenes. In order to render a view, we just need to declare it with a template property set. var SampleView = Backbone.Marionette.ItemView.extend({ template : '#sample-template' }); Next, we just create a Backbone model, and we pass it to the ItemView constructor. var SampleModel = Backbone.Model.extend({ defaults : { value1 : "A random Value", value2 : "Another Random Value" } }) var sampleModel = new SampleModel(); var sampleView = new SampleView({model:sampleModel); And then the only thing left is to call the render function. sampleView.render(); If you want to see it running, please go through this JSFiddle that illustrates the previous code: http://jsfiddle.net/rayweb_on/VS9hA/ One thing to note is that we just needed one line to specify the template, and Marionette did the rest by rendering our view with the specified template. Notice that in this example, we used the ItemView constructor; we should not use Marionette.View directly, as it does not have many functionalities of its own. It just serves as the base for other views. So some of the following examples of the functionalities provided by Marionette.View will be demonstrated using ItemView, as this view inherits all of these functionalities through extension. As we saw in the previous example, ItemView works perfectly for rendering a single model using a template, but what about rendering a collection of models? If you just need to render, for example, a list of books or categories, you still can use ItemView. To accomplish this, the template that you would assign to ItemView must know how to handle the creation of the DOM to properly display that list of items. Let's render a list of books. The Backbone model will have two properties: the book name and the book ID. We just want to create a list of links using the book name as the value to be displayed; the ID of the book will be used to create a link to see the specific book. First, let's create the book Backbone model for this example and its collection: var BookModel = Backbone.Model.extend({ defaults : { id : "1", name : "First", } }); var BookCollection = Backbone.Collection.extend({ model : BookModel }); Now let's instantiate the collection and add three models to it: var bookModel = new BookModel(); var bookModel2 = new BookModel({id:"2",name:"second"}); var bookModel3 = new BookModel({id:"3",name:"third"}); var bookCollection = new BookCollection(); bookCollection.add(bookModel); bookCollection.add(bookModel2); bookCollection.add(bookModel3); In our HTML, let's create the template to be used in this view; the template should look like the following: <script id="books-template" type="text/html"> <ul> <% _.each(items, function(item){ %> <li><a href="book/'+<%= item.id %> +"><%= item.name %> </li> <% }); %> </ul> </script> Now we could render the book list using the following code snippet: var BookListView = Marionette.ItemView.extend({ template: "#books-template" }); var view = new BookListView ({ collection: bookCollection }); view.Render(); If you want to see it in action, go to the working code in JSFiddle at http://jsfiddle.net/rayweb_on/8QAgQ/. The previous code would produce an unordered list of books with links to the specific book. Again, we gained the benefit of writing very little code once again, as we didn't need to specify the Render function, which could be misleading, because the ItemView is perfectly capable of rendering a model or a collection. Whether to use CollectionView or ItemView will depend on what we are trying to accomplish. If we need a set of individual views with its own functionality, CollectionView is the right choice, as we will see when we get to the point of reviewing it. But if we just need to render the values of a collection, ItemView would be the perfect choice. Handling events in the views To keep track of model events or collection events, we must write the following code snippet on a regular Backbone view: this.listenTo(this.model, "change:title", this.titleChanged); this.listenTo(this.collection, "add", this.collectionChanged); To start these events, we use the following handler functions: titleChanged: function(model, value){alert("changed");}, collectionChanged: function(model, value){alert("added");}, This still works fine in Marionette, but we can accomplish the same thing by declaring these events using the following configuration hash: modelEvents: { "change:title": "titleChanged" }, collectionEvents: { "add": "collectionChanged" }, This will give us exactly the same result, but the configuration hash is very convenient as we can keep adding events to our model or collection, and the code is cleaner and very easy to follow. The modelEvents and collectionEvents are not the only configuration hash sets that we have available in each one of the Marionette views; the UI configuration hash is also available. It may be the case that one of the DOM elements on your view will be used many times to read its value, and doing this using jQuery can not be optimal in terms of performance. Also, we would have the jQuery reference in several places, repeating ourselves and making our code less DRY. Inside a Backbone view, we can define a set of events that will be fired once an action is taken in the DOM; for instance, we pass the function that we want to handle in this event at the click of a button. events : { "click #button2" : "updateValue" }, This will invoke the updateValue function once we click on button2. This works fine, but what about calling a method that is not inside the view? To accomplish this, Marionette provides the triggers functionality that will fire events which can be listened to outside of your view. To declare a trigger, we can use the same syntax used in the events object as follows: triggers : { "click #button1": "trigger:alert"}, And then, we can listen to that event somewhere else using the following code: sampleView.on("trigger:alert", function(args){ alert(args.model.get("value2")); }); In the previous code, we used the model to alert and display the value of the property, value2. The args parameter received by the function will contain objects that you can use: The view that fired the trigger The Backbone model or collection of that view UI and templates While working with a view, you will need a reference to a particular HTML element through jQuery in more than one place in your view. This means you will make a reference to a button during initialization and in few other methods of the view. To avoid having the jQuery selector duplicated on each of these methods, you can map that UI element in a hash so that the selector is preserved. If you need to change it, the change will be done in a single place. To create this mapping of UI elements, we need to add the following declaration: ui: { quantity: "#quantity" saveButton : "#Save" }, And to make use of these mapper UI elements, we just need to refer them inside any function by the name given in the configuration. validateQuantity: function() { if (this.ui.quantity.val() > 0 { this.ui.saveButton.addClass('active'); } } There will be times when you need to pass a different template to your view. To do this in Marionette, we remove the template declaration and instead add a function called getTemplate. The following code snippet would illustrate the use of this function: getTemplate: function(){ if (this.model.get("foo"){ return "#sample-template"; }else { return "#a-different-template"; } }, In this case, we check the existence of the property foo; if it's not present, we use a different template and that will be it. You don't need to specify the render function because it will work the same way as declaring a template variable as seen in one of the previous examples. If you want to learn more about all the concepts that we have discussed so far, please refer to the jsFiddle link: http://jsfiddle.net/rayweb_on/NaHQS/. If you find yourself needing to make calculations involving a complicated process while rendering a value, you can make use of templeteHelpers that are functions contained in an object called templateHelpers. Let's look at an example that will illustrate its use better. Suppose we need to show the value of a book but are offering a discount that we need to calculate, use the following code: var PriceView = Backbone.Marionette.ItemView.extend({ template: "#price-template", templateHelpers: { calculatePrice: function(){ // logic to calculate the price goes here return price; } } }); As you can see the in the previous code, we declared an object literal that will contain functions that can be called from the templates. <script id="my-template" type="text/html"> Take this book with you for just : <%= calculatePrice () %> </script> Marionette.CollectionView Rendering a list of things like books inside one view is possible, but we want to be able to interact with each item. The solution for this will be to create a view one-by-one with the help of a loop. But Marionette solves this in a very elegant way by introducing the concept of CollectionView that will render a child view for each of the elements that we have in the collection we want to display. A good example to put into practice could be to list the books by category and create a Collection view. This is incredible easy. First, you need to define how each of your items should be displayed; this means how each item will be transformed in a view. For our categories example, we want each item to be a list <li> element and part of our collection; the <ul> list will contain each category view. We first declare ItemView as follows: var CategoryView = Backbone.Marionette.ItemView.extend({ tagName : 'li', template: "#categoryTemplate", }); Then we declare CollectionView, which specifies the view item to use. var CategoriesView = Backbone.Marionette.CollectionView.extend({ tagName : 'ul', className : 'unstyled', itemView: CategoryView }); A good thing to notice is that even when we are using Marionette views, we are still able to use the standard properties that Backbone views offer, such as tagName and ClassName. Finally, we create a collection and we instantiate CollectionView by passing the collection as a parameter. var categoriesView = new CategoriesView({collection:categories); categoriesView.render(); And that's it. Simple huh? The advantage of using this view is that it will render a view for each item, and it can have a lot of functionality; we can control all those views in the CollectionView that serves as a container. You can see it in action at http://jsfiddle.net/rayweb_on/7usdJ/. Marionette.CompositeView The Marionette.Composite view offers the possibility of not only rendering a model or collection models but, also the possibility of rendering both a model and a collection. That's why this view fits perfectly in our BookStore website. We will be adding single items to the shopping cart, books in this case, and we will be storing these books in a collection. But we need to calculate the subtotal of the order, show the calculated tax, and an order total; all of these properties will be part of our totals model that we will be displaying along with the ordered books. But there is a problem. What should we display in the order region when there are no items added? Well, in the CompositeView and the CollectionView, we can set an emptyView property, which will be a view to show in case there are no models in the collection. Once we add a model, we can then render the item and the totals model. Perhaps at this point, you may think that you lost control over your render functionality, and there will be cases where you need to do things to modify your HTML. Well, in that scenario, you should use the onRender() function, which is a very helpful method that will allow you to manipulate the DOM just after your render method was called. Finally, we would like to set a template with some headers. These headers are not part of an ItemView, so how can we display it? Let's have a look at part of the code snippet that explains how each part solves our needs. var OrderListView = Backbone.Marionette.CompositeView.extend({ tagName: "table", template: "#orderGrid", itemView: CartApp.OrderItemView, emptyView: CartApp.EmptyOrderView, className: "table table-hover table-condensed", appendHtml: function (collectionView, itemView) { collectionView.$("tbody").append(itemView.el); }, So far we defined the view and set the template; the Itemview and EmptyView properties will be used to render our view. The onBeforeRender is a function that will be called, as the name indicates, before the render method; this function will allow us to calculate the totals that will be displayed in the total model. onBeforeRender: function () { var subtotal = this.collection.getTotal(); var tax = subtotal * .08; var total = subtotal + tax; this.model.set({ subtotal: subtotal }); this.model.set({ tax: tax }); this.model.set({ total: total }); }, The onRender method is used here to check whether there are no models in the collection (that is, the user hasn't added a book to the shopping cart). If not, we should not display the header and footer regions of the view. onRender: function () { if (this.collection.length > 0) { this.$('thead').removeClass('hide'); this.$('tfoot').removeClass('hide'); } }, As we can see, Marionette does a great job offering functions that can remove a lot of boilerplate code and also give us full control over what is being rendered. Summary This article covered the introduction and usage of view types that Marionette has. Now you must be quite familiar with the Marionette.View and Marionette.ItemView view types of Marionette. Resources for Article: Further resources on this subject: Mobile Devices [Article] Puppet: Integrating External Tools [Article] Understanding Backbone [Article]
Read more
  • 0
  • 0
  • 5850

article-image-conozca-qlikview
Packt
02 Jan 2014
8 min read
Save for later

Conozca QlikView

Packt
02 Jan 2014
8 min read
(Para más recursos relacionados con este tema, vea aquí.) ¿Qué es QlikView? QlikView es una herramienta computacional desarrollada por QlikTech, una compañía que fue fundada en Suecia en 1993, pero actualmente con sede a Estados Unidos. QlikView es una herramienta usada para Inteligencia de Negocios, comúnmente abreviada como BI por las siglas de su denominación en inglés: Business Intelligence . La inteligencia de negocios es definida por Gartner, una firma líder de analistas de la industria, como: Un término general que incluye la aplicación, infraestructura y herramientas, y mejores prácticas que permiten el acceso a información y análisis de la misma para mejorar y optimizar el proceso de toma de decisiones y desempeño de una compañía. Siguiendo esta definición, QlikView es una herramienta que permite el acceso a la información y posibilita el análisis de los datos, lo cual a su vez mejora y optimiza el proceso de toma de decisiones de negocio y por ende también el desempeño del mismo. Históricamente, la Inteligencia de Negocios ha sido comandada principalmente por los departamentos de Tecnologías de Información en las empresas. Los departamentos de TI eran responsables de todo el ciclo de vida de una solución de Inteligencia de Negocios, desde extraer los datos hasta entregar los reportes finales, análisis y cuadros de mando. Aunque este modelo funciona bien para la distribución de reportes estáticos predefinidos, la mayoría de las empresas se han ido dando cuenta que no cumple con las necesidades de sus usuarios de negocio. Como TI controla de cerca los datos y herramientas, los usuarios comúnmente experimentan largos tiempos de espera cuando surgen nuevas preguntas de negocio que no pueden ser respondidas con los reportes estándar. ¿Cómo se diferencia QlikView de herramientas tradicionales de BI? QlikTech se enorgullece de abordar la Inteligencia de Negocios de una manera distinta a lo que compañías como Oracle, SAP, e IBM – descritas por QlikTech como proveedores tradicionales de BI – ofrecen. QlikTech busca poner las herramientas en manos del usuario de negocio, permitiéndole ser autosuficiente, ya que así puede realizar sus propios análisis. Las firmas independientes de analistas de la industria han notado también este acercamiento distinto. En 2011, Gartner creó una subcategoría para herramientas de Descubrimiento de Datos en su evaluación anual de mercado, el Cuadrante Mágico de plataformas de Inteligencia de Negocios . QlikView fue el abanderado en esta nueva categoría de herramientas de BI. QlikTech prefiere describir su producto como una herramienta de Descubrimiento del Negocio en lugar de Descubrimiento de Datos. Sostiene que descubrir cosas sobre el negocio es mucho más importante que descubrir datos. El siguiente diagrama ilustra este paradigma. Fuente: QlikTech Además de la diferencia en quién usa la herramienta – usuarios de TI contra usuarios de negocio – hay algunas otras funcionalidades que diferencian a QlikView de otras soluciones. Experiencia de usuario asociativa La principal diferencia entre QlikView y otras soluciones de BI es la experiencia de usuario asociativa. Mientras que las soluciones de BI tradicionales usan caminos predefinidos para navegar y explorar datos, QlikView permite a los usuarios tomar cualquier ruta que deseen para realizar análisis. Esto resulta en una manera mucho más intuitiva de navegar los datos. QlikTech describe esto como "trabajar de la forma en que trabaja la mente humana". En la siguiente imagen se muestra un ejemplo. Mientras que en una solución típica de BI tendríamos que comenzar seleccionando una Región para después entrar paso a paso en el camino jerárquico definido, en QlikView podemos elegir cualquier punto de entrada que deseemos – Región , Estado , Producto , o Vendedor . Al ir navegando los datos, se nos presenta solo la información relacionada a nuestra selección y, para nuestra siguiente selección, podemos elegir cualquier camino que deseemos. La navegación es infinitamente flexible. Adicionalmente, la interfaz de usuario QlikView nos permite ver los datos que están asociados a nuestra selección. Por ejemplo, la siguiente imagen de pantalla (del documento demostrativo de QlikTech llamado What's New in QlikView 11 ) muestra un Cuadro de Mando en QlikView en el que hay dos valores seleccionados. En el campo Quarter , está seleccionado el valor Q3 , y en el campo Sales Reps , está seleccionado Cart Lynch . Podemos ver esto porque los valores correspondientes están en color verde, lo cual significa que dichos valores han sido seleccionados. Cuando se hace una selección, la interfaz se actualiza automáticamente no solo para mostrar los datos que están asociados a esta nueva consulta, sino también los datos que no están asociados con dicha selección. Los datos asociados aparecen con un fondo blanco, mientras que los datos no asociados tienen un fondo gris. Algunas veces las asociaciones pueden ser bastante obvias; no es sorpresa que el tercer trimestre del año tenga asociado los meses de Julio, Agosto y Septiembre. Sin embargo, en otras ocasiones nos encontramos con otras asociaciones no tan obvias, como por ejemplo que Carl Lynch no ha vendido ningún producto en Alemania o España. Esta información extra, que no se ve en herramientas tradicionales de BI, puede ser de gran valor ya que ofrece un nuevo punto de comienzo para exploración de datos. Tecnología El principal diferenciador tecnológico de QlikView es que utiliza un modelo de datos en memoria, es decir, que toda la información con que interactúa el usuario está guardada en RAM en lugar de utilizar disco. Como el uso de RAM es mucho más rápido que disco, los tiempos de respuesta son muy rápidos, generando así una experiencia de usuario muy fluida. En una sección posterior de este capítulo, ahondaremos un poco más en el tema de la tecnología detrás de QlikView. Adopción Hay otra diferencia entre QlikView y otras soluciones tradicionales de BI que radica en la forma en que se implementa dentro de una compañía. Mientras que las soluciones tradicionales de BI son típicamente implementadas de arriba hacia abajo – en donde TI selecciona una herramienta de BI para toda la compañía – QlikView comúnmente toma una ruta de adopción de abajo hacia arriba. Los usuarios de negocio de un solo departamento la implementan localmente, y su uso se expande desde ahí. QlikView se puede descargar de manera gratuita para uso personal. A esta versión se le llama QlikView Personal Edition o PE. Los documentos creados en la edición personal de QlikView pueden ser abiertos por usuarios con licencia completa del software o publicarse a través de QlikView Server. La limitación es que, a excepción de algunos documentos habilitados por QlikTech para PE, un usuario de la edición personal de QlikView no puede abrir documentos creados por otro usuario o en otro equipo; algunas veces tampoco se pueden abrir sus propios documentos si fueron abiertos y guardados por otro usuario o instancia de servidor. Frecuentemente, un usuario de negocio decidirá descargar QlikView para ver si puede resolver un problema de negocio. Cuando otros usuarios dentro del departamento ven el software, se vuelven cada vez más entusiastas sobre la herramienta, y cada quien baja el programa. Para poder compartir documentos, deciden comprar algunas licencias para el departamento. Luego, otros departamentos comienzan a notarlo también, y QlikView gana tracción dentro de la organización. Poco tiempo después, TI y los directivos de la empresa comienzan también a notarlo, lo cual lleva eventualmente a la adopción de QlikView en toda la empresa. QlikView facilita cada paso del proceso, escalando de una implementación en una computadora personal hasta implementaciones a nivel organización con miles de usuarios. La siguiente imagen ilustra este crecimiento dentro de una organización: Conforme la popularidad e historial de QlikView en la organización crece, gana cada vez más visibilidad a nivel empresa. Aunque la ruta de adopción descrita anteriormente es probablemente el escenario más común, no es extraño ahora que una compañía opte por una implementación de QlikView en modo top-down a nivel empresa desde un inicio.
Read more
  • 0
  • 0
  • 3160
Modal Close icon
Modal Close icon